1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <vcl/svapp.hxx>
21
22 #include <pagepreviewlayout.hxx>
23 #include <prevwpage.hxx>
24
25 #include <algorithm>
26 #include <tools/fract.hxx>
27 #include <vcl/window.hxx>
28 #include <vcl/settings.hxx>
29
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>
41
42 #include <IDocumentDeviceAccess.hxx>
43
44 // methods to initialize page preview layout
45
SwPagePreviewLayout(SwViewShell & _rParentViewShell,const SwRootFrame & _rLayoutRootFrame)46 SwPagePreviewLayout::SwPagePreviewLayout( SwViewShell& _rParentViewShell,
47 const SwRootFrame& _rLayoutRootFrame )
48 : mrParentViewShell( _rParentViewShell ),
49 mrLayoutRootFrame ( _rLayoutRootFrame )
50 {
51 Clear_();
52
53 mbBookPreview = false;
54 mbBookPreviewModeToggled = false;
55
56 mbPrintEmptyPages = mrParentViewShell.getIDocumentDeviceAccess().getPrintData().IsPrintEmptyPages();
57 }
58
Clear_()59 void SwPagePreviewLayout::Clear_()
60 {
61 mbLayoutInfoValid = mbLayoutSizesValid = mbPaintInfoValid = false;
62
63 maWinSize.setWidth( 0 );
64 maWinSize.setHeight( 0 );
65 mnCols = mnRows = 0;
66
67 ClearPreviewLayoutSizes();
68
69 mbDoesLayoutRowsFitIntoWindow = false;
70 mbDoesLayoutColsFitIntoWindow = false;
71
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();
87
88 mbInPaint = false;
89 mbNewLayoutDuringPaint = false;
90 }
91
ClearPreviewLayoutSizes()92 void SwPagePreviewLayout::ClearPreviewLayoutSizes()
93 {
94 mnPages = 0;
95
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;
104 }
105
ClearPreviewPageData()106 void SwPagePreviewLayout::ClearPreviewPageData()
107 {
108 maPreviewPages.clear();
109 }
110
111 /** calculate page preview layout sizes
112
113 */
CalcPreviewLayoutSizes()114 void SwPagePreviewLayout::CalcPreviewLayoutSizes()
115 {
116 vcl::RenderContext* pRenderContext = mrParentViewShell.GetOut();
117 // calculate maximal page size; calculate also number of pages
118
119 const SwPageFrame* pPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
120 while ( pPage )
121 {
122 if ( !mbBookPreview && !mbPrintEmptyPages && pPage->IsEmptyPage() )
123 {
124 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
125 continue;
126 }
127
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());
136 }
137 // calculate and set column width and row height
138 mnColWidth = maMaxPageSize.Width() + gnXFree;
139 mnRowHeight = maMaxPageSize.Height() + gnYFree;
140
141 // calculate and set preview layout width and height
142 mnPreviewLayoutWidth = mnCols * mnColWidth + gnXFree;
143 mnPreviewLayoutHeight = mnRows * mnRowHeight + gnYFree;
144
145 // calculate document rectangle in preview layout
146 {
147 Size aDocSize;
148 // document width
149 aDocSize.setWidth( mnPreviewLayoutWidth );
150
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 );
159 }
160 }
161
162 /** init page preview layout
163
164 initialize the page preview settings for a given layout.
165
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.
170 */
Init(const sal_uInt16 _nCols,const sal_uInt16 _nRows,const Size & _rPxWinSize)171 void SwPagePreviewLayout::Init( const sal_uInt16 _nCols,
172 const sal_uInt16 _nRows,
173 const Size& _rPxWinSize
174 )
175 {
176 // check environment and parameters
177 {
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;
182
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;
188 }
189
190 // environment and parameters ok
191
192 // clear existing preview settings
193 Clear_();
194
195 // set layout information columns and rows
196 mnCols = _nCols;
197 mnRows = _nRows;
198
199 CalcPreviewLayoutSizes();
200
201 // validate layout information
202 mbLayoutInfoValid = true;
203
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;
211 {
212 // adjust scaling for Drawing layer.
213 aYScale *= Fraction( 1000, 1 );
214 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) );
220
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() );
227 }
228
229 // set window size in twips
230 maWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize );
231 // validate layout sizes
232 mbLayoutSizesValid = true;
233 }
234
235 /** apply new zoom at given view shell */
ApplyNewZoomAtViewShell(sal_uInt8 _aNewZoom)236 void SwPagePreviewLayout::ApplyNewZoomAtViewShell( sal_uInt8 _aNewZoom )
237 {
238 SwViewOption aNewViewOptions = *(mrParentViewShell.GetViewOptions());
239 if ( aNewViewOptions.GetZoom() != _aNewZoom )
240 {
241 aNewViewOptions.SetZoom( _aNewZoom );
242 //#i19975# - consider zoom type.
243 aNewViewOptions.SetZoomType( SvxZoomType::PERCENT );
244 mrParentViewShell.ApplyViewOptions( aNewViewOptions );
245 }
246 }
247
248 /** method to adjust page preview layout to document changes
249
250 */
ReInit()251 void SwPagePreviewLayout::ReInit()
252 {
253 // check environment and parameters
254 {
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;
260 }
261
262 ClearPreviewLayoutSizes();
263 CalcPreviewLayoutSizes();
264 }
265
266 // methods to prepare paint of page preview
267
268 /** prepare paint of page preview
269
270 delete parameter _onStartPageVirtNum
271
272 @note _nProposedStartPageNum, _onStartPageNum are absolute
273 */
Prepare(const sal_uInt16 _nProposedStartPageNum,const Point & rProposedStartPos,const Size & _rPxWinSize,sal_uInt16 & _onStartPageNum,tools::Rectangle & _orDocPreviewPaintRect,const bool _bStartWithPageAtFirstCol)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
280 )
281 {
282 sal_uInt16 nProposedStartPageNum = ConvertAbsoluteToRelativePageNum( _nProposedStartPageNum );
283 // check environment and parameters
284 {
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;
290
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;
296
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;
305
306 bool bWinSizeValid = _rPxWinSize.Width() != 0 && _rPxWinSize.Height() != 0;
307 OSL_ENSURE( bWinSizeValid, "no window size - no prepare of preview paint");
308 if ( !bWinSizeValid )
309 return false;
310
311 bool bStartInfoValid = _nProposedStartPageNum > 0 ||
312 rProposedStartPos != Point(0,0);
313 if ( !bStartInfoValid )
314 nProposedStartPageNum = 1;
315 }
316
317 // environment and parameter ok
318
319 // update window size at preview setting data
320 maWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize );
321
322 mbNoPageVisible = false;
323 if ( nProposedStartPageNum > 0 )
324 {
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 )
330 {
331 // leaving left-top-corner blank is
332 // controlled by <mbBookPreview>.
333 if ( mbBookPreview &&
334 ( nProposedStartPageNum == 1 || nRowOfProposed == 1 )
335 )
336 mnPaintPhyStartPageNum = 1;
337 else
338 mnPaintPhyStartPageNum = nProposedStartPageNum - (nColOfProposed-1);
339 }
340 else
341 mnPaintPhyStartPageNum = nProposedStartPageNum;
342
343 mnPaintPhyStartPageNum = ConvertRelativeToAbsolutePageNum( mnPaintPhyStartPageNum );
344
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 );
361 }
362 else
363 {
364 // determine column and row of proposed start position.
365 // Note: paint starts at point (0,0)
366 const sal_uInt16 nColOfProposed =
367 static_cast<sal_uInt16>(rProposedStartPos.X() / mnColWidth) + 1;
368 const sal_uInt16 nRowOfProposed =
369 static_cast<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 )
375 )
376 mnPaintPhyStartPageNum = 1;
377 else
378 {
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 )
385 {
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;
390 }
391 }
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;
402 }
403
404 // determine additional paint offset, if preview layout fits into window.
405 CalcAdditionalPaintOffset();
406
407 // determine rectangle to be painted from document preview
408 CalcDocPreviewPaintRect();
409 _orDocPreviewPaintRect = maPaintedPreviewDocRect;
410
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() )
415 {
416 maPaintedPreviewDocRect.Move(
417 -(maWinSize.Width() - maPaintedPreviewDocRect.GetWidth()), 0 );
418 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
419 _rPxWinSize, _onStartPageNum,
420 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
421 }
422
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() )
428 {
429 if ( mbDoesLayoutRowsFitIntoWindow )
430 {
431 if ( maPaintedPreviewDocRect.GetHeight() < mnPreviewLayoutHeight)
432 {
433 maPaintedPreviewDocRect.Move(
434 0, -(mnPreviewLayoutHeight - maPaintedPreviewDocRect.GetHeight()) );
435 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
436 _rPxWinSize, _onStartPageNum,
437 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
438 }
439 }
440 else
441 {
442 maPaintedPreviewDocRect.Move(
443 0, -(maWinSize.Height() - maPaintedPreviewDocRect.GetHeight()) );
444 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
445 _rPxWinSize, _onStartPageNum,
446 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
447 }
448 }
449
450 // determine preview pages - visible pages with needed data for paint and
451 // accessible pages with needed data.
452 CalcPreviewPages();
453
454 // OD 07.11.2003 #i22014# - indicate new layout, if print preview is in paint
455 if ( mbInPaint )
456 {
457 mbNewLayoutDuringPaint = true;
458 }
459
460 // validate paint data
461 mbPaintInfoValid = true;
462
463 // return start page
464 _onStartPageNum = mnPaintPhyStartPageNum;
465
466 return true;
467 }
468
469 /** calculate additional paint offset
470
471 */
CalcAdditionalPaintOffset()472 void SwPagePreviewLayout::CalcAdditionalPaintOffset()
473 {
474 if ( mnPreviewLayoutWidth <= maWinSize.Width() &&
475 maPaintStartPageOffset.X() <= 0 )
476 {
477 mbDoesLayoutColsFitIntoWindow = true;
478 maAdditionalPaintOffset.setX( (maWinSize.Width() - mnPreviewLayoutWidth) / 2 );
479 }
480 else
481 {
482 mbDoesLayoutColsFitIntoWindow = false;
483 maAdditionalPaintOffset.setX( 0 );
484 }
485
486 if ( mnPreviewLayoutHeight <= maWinSize.Height() &&
487 maPaintStartPageOffset.Y() <= 0 )
488 {
489 mbDoesLayoutRowsFitIntoWindow = true;
490 maAdditionalPaintOffset.setY( (maWinSize.Height() - mnPreviewLayoutHeight) / 2 );
491 }
492 else
493 {
494 mbDoesLayoutRowsFitIntoWindow = false;
495 maAdditionalPaintOffset.setY( 0 );
496 }
497 }
498
499 /** calculate painted preview document rectangle
500
501 */
CalcDocPreviewPaintRect()502 void SwPagePreviewLayout::CalcDocPreviewPaintRect()
503 {
504 Point aTopLeftPos = maPaintPreviewDocOffset;
505 maPaintedPreviewDocRect.SetPos( aTopLeftPos );
506
507 Size aSize;
508 if ( mbDoesLayoutColsFitIntoWindow )
509 aSize.setWidth( std::min( 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( 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 );
521 }
522
523 /** calculate preview pages
524
525 */
CalcPreviewPages()526 void SwPagePreviewLayout::CalcPreviewPages()
527 {
528 vcl::RenderContext* pRenderContext = mrParentViewShell.GetOut();
529 ClearPreviewPageData();
530
531 if ( mbNoPageVisible )
532 return;
533
534 // determine start page frame
535 const SwPageFrame* pStartPage = mrLayoutRootFrame.GetPageByPageNum( mnPaintPhyStartPageNum );
536
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 );
545 }
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 );
551 }
552 aInitialPaintOffset += maAdditionalPaintOffset;
553
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()
563 )
564 {
565 if ( !mbBookPreview && !mbPrintEmptyPages && pPage->IsEmptyPage() )
566 {
567 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
568 continue;
569 }
570
571 pPage->Calc(pRenderContext);
572
573 // consider only pages, which have to be painted.
574 if ( nCurrCol < mnPaintStartCol )
575 {
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;
587 }
588 if ( aCurrPaintOffset.X() < maWinSize.Width() )
589 {
590 // leaving left-top-corner blank is
591 // controlled by <mbBookPreview>.
592 if ( mbBookPreview && pPage->GetPhyPageNum() == 1 && mnCols != 1 && nCurrCol == 1
593 )
594 {
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;
603 }
604
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) );
610 }
611 else
612 {
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) );
618 }
619
620 // prepare data for next loop
621 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
622
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 )
629 {
630 ++nConsideredRows;
631 aCurrPaintOffset.setX( aInitialPaintOffset.X() );
632 nCurrCol = 1;
633 aCurrPaintOffset.AdjustY(mnRowHeight );
634 }
635 }
636 }
637
638 /** determines preview data for a given page and a given preview offset
639
640 OD 13.12.2002 #103492#
641 */
CalcPreviewDataForPage(const SwPageFrame & _rPage,const Point & _rPreviewOffset,PreviewPage * _opPreviewPage)642 void SwPagePreviewLayout::CalcPreviewDataForPage( const SwPageFrame& _rPage,
643 const Point& _rPreviewOffset,
644 PreviewPage* _opPreviewPage )
645 {
646 // page frame
647 _opPreviewPage->pPage = &_rPage;
648 // size of page frame
649 if ( _rPage.IsEmptyPage() )
650 {
651 if ( _rPage.GetPhyPageNum() % 2 == 0 )
652 _opPreviewPage->aPageSize = _rPage.GetPrev()->getFrameArea().SSize();
653 else
654 _opPreviewPage->aPageSize = _rPage.GetNext()->getFrameArea().SSize();
655 }
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() )
667 {
668 _opPreviewPage->aLogicPos = _opPreviewPage->aPreviewWinPos;
669 _opPreviewPage->aMapOffset = Point( 0, 0 );
670 }
671 else
672 {
673 _opPreviewPage->aLogicPos = _rPage.getFrameArea().Pos();
674 _opPreviewPage->aMapOffset = _opPreviewPage->aPreviewWinPos - _opPreviewPage->aLogicPos;
675 }
676 }
677
678 /** enable/disable book preview
679
680 OD 2004-03-04 #i18143#
681 */
SetBookPreviewMode(const bool _bEnableBookPreview,sal_uInt16 & _onStartPageNum,tools::Rectangle & _orDocPreviewPaintRect)682 bool SwPagePreviewLayout::SetBookPreviewMode( const bool _bEnableBookPreview,
683 sal_uInt16& _onStartPageNum,
684 tools::Rectangle& _orDocPreviewPaintRect )
685 {
686 if ( mbBookPreview != _bEnableBookPreview)
687 {
688 mbBookPreview = _bEnableBookPreview;
689 // re-initialize page preview layout
690 ReInit();
691 // re-prepare page preview layout
692 {
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() )
698 {
699 aProposedStartPos.setY( maPreviewDocRect.Bottom() );
700 }
701 Prepare( 0, aProposedStartPos,
702 mrParentViewShell.GetOut()->LogicToPixel( maWinSize ),
703 _onStartPageNum, _orDocPreviewPaintRect );
704 mbBookPreviewModeToggled = false;
705 }
706
707 return true;
708 }
709
710 return false;
711 }
712
713 // methods to determine new data for changing the current shown part of the
714 // document preview.
715
716 /** calculate start position for new scale
717
718 */
GetPreviewStartPosForNewScale(const Fraction & _aNewScale,const Fraction & _aOldScale,const Size & _aNewWinSize) const719 Point SwPagePreviewLayout::GetPreviewStartPosForNewScale(
720 const Fraction& _aNewScale,
721 const Fraction& _aOldScale,
722 const Size& _aNewWinSize ) const
723 {
724 Point aNewPaintStartPos = maPaintedPreviewDocRect.TopLeft();
725 if ( _aNewScale < _aOldScale )
726 {
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() )
731 {
732 aNewPaintStartPos.AdjustX( -(
733 (_aNewWinSize.Width() - maPaintedPreviewDocRect.GetWidth()) / 2) );
734 if ( aNewPaintStartPos.X() < 0)
735 aNewPaintStartPos.setX( 0 );
736 }
737
738 if ( !mbDoesLayoutRowsFitIntoWindow )
739 {
740 // increase paint height by moving start point to top.
741 if ( mnPreviewLayoutHeight < _aNewWinSize.Height() )
742 {
743 aNewPaintStartPos.setY(
744 (mnPaintStartRow - 1) * mnRowHeight );
745 }
746 else if ( maPaintedPreviewDocRect.GetHeight() < _aNewWinSize.Height() )
747 {
748 aNewPaintStartPos.AdjustY( -(
749 (_aNewWinSize.Height() - maPaintedPreviewDocRect.GetHeight()) / 2) );
750 if ( aNewPaintStartPos.Y() < 0)
751 aNewPaintStartPos.setY( 0 );
752 }
753 }
754 }
755 else
756 {
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() )
763 {
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( 0L, maPreviewDocRect.Bottom() - mnPreviewLayoutHeight ) );
770 }
771 }
772
773 return aNewPaintStartPos;
774 }
775
776 /** determines, if page with given page number is visible in preview
777
778 @note _nPageNum is absolute
779 */
IsPageVisible(const sal_uInt16 _nPageNum) const780 bool SwPagePreviewLayout::IsPageVisible( const sal_uInt16 _nPageNum ) const
781 {
782 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
783 return pPreviewPage && pPreviewPage->bVisible;
784 }
785
786 /** calculate data to bring new selected page into view.
787
788 @note IN/OUT parameters are absolute page numbers!!!
789 */
CalcStartValuesForSelectedPageMove(const sal_Int16 _nHoriMove,const sal_Int16 _nVertMove,sal_uInt16 & _orNewSelectedPage,sal_uInt16 & _orNewStartPage,Point & _orNewStartPos) const790 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
796 {
797 // determine position of current selected page
798 sal_uInt16 nTmpRelSelPageNum = ConvertAbsoluteToRelativePageNum( mnSelectedPageNum );
799 sal_uInt16 nNewRelSelectedPageNum = nTmpRelSelPageNum;
800
801 const sal_uInt16 nCurrRow = GetRowOfPage(nTmpRelSelPageNum);
802
803 // determine new selected page number
804 {
805 if ( _nHoriMove != 0 )
806 {
807 if ( (nNewRelSelectedPageNum + _nHoriMove) < 1 )
808 nNewRelSelectedPageNum = 1;
809 else if ( (nNewRelSelectedPageNum + _nHoriMove) > mnPages )
810 nNewRelSelectedPageNum = mnPages;
811 else
812 nNewRelSelectedPageNum = nNewRelSelectedPageNum + _nHoriMove;
813 }
814 if ( _nVertMove != 0 )
815 {
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 );
822 }
823 }
824
825 sal_uInt16 nNewStartPage = mnPaintPhyStartPageNum;
826 Point aNewStartPos(0,0);
827
828 const sal_uInt16 nNewAbsSelectedPageNum = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
829 if ( !IsPageVisible( nNewAbsSelectedPageNum ) )
830 {
831 if ( _nHoriMove != 0 && _nVertMove != 0 )
832 {
833 OSL_FAIL( "missing implementation for moving preview selected page horizontal AND vertical");
834 return;
835 }
836
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 )
844 {
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 )
851 {
852 // Note: decrease new proposed start page number by one,
853 // because of blank left-top-corner
854 --nNewStartPage;
855 }
856 nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewStartPage );
857 }
858 else
859 {
860 // new proposed start page = new selected page.
861 nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
862 }
863 }
864
865 _orNewSelectedPage = nNewAbsSelectedPageNum;
866 _orNewStartPage = nNewStartPage;
867 _orNewStartPos = aNewStartPos;
868 }
869
870 /** checks, if given position is inside a shown document page */
871 struct PreviewPosInsidePagePred
872 {
873 const Point mnPreviewPos;
PreviewPosInsidePagePredPreviewPosInsidePagePred874 explicit PreviewPosInsidePagePred(const Point& rPreviewPos)
875 : mnPreviewPos( rPreviewPos )
876 {}
operator ()PreviewPosInsidePagePred877 bool operator() ( const std::unique_ptr<PreviewPage> & _pPreviewPage )
878 {
879 if ( _pPreviewPage->bVisible )
880 {
881 tools::Rectangle aPreviewPageRect( _pPreviewPage->aPreviewWinPos, _pPreviewPage->aPageSize );
882 return aPreviewPageRect.IsInside( mnPreviewPos );
883 }
884 return false;
885 }
886 };
887
IsPreviewPosInDocPreviewPage(const Point & rPreviewPos,Point & _orDocPos,bool & _obPosInEmptyPage,sal_uInt16 & _onPageNum) const888 bool SwPagePreviewLayout::IsPreviewPosInDocPreviewPage( const Point& rPreviewPos,
889 Point& _orDocPos,
890 bool& _obPosInEmptyPage,
891 sal_uInt16& _onPageNum ) const
892 {
893 // initialize variable parameter values.
894 _orDocPos.setX( 0 );
895 _orDocPos.setY( 0 );
896 _obPosInEmptyPage = false;
897 _onPageNum = 0;
898
899 auto aFoundPreviewPageIter =
900 std::find_if( maPreviewPages.begin(), maPreviewPages.end(),
901 PreviewPosInsidePagePred( rPreviewPos ) );
902
903 if ( aFoundPreviewPageIter != maPreviewPages.end() )
904 {
905 // given preview position is inside a document page.
906 _onPageNum = (*aFoundPreviewPageIter)->pPage->GetPhyPageNum();
907 _obPosInEmptyPage = (*aFoundPreviewPageIter)->pPage->IsEmptyPage();
908 if ( !_obPosInEmptyPage )
909 {
910 // given preview position inside a normal page
911 _orDocPos = rPreviewPos -
912 (*aFoundPreviewPageIter)->aPreviewWinPos +
913 (*aFoundPreviewPageIter)->aLogicPos;
914 return true;
915 }
916 }
917
918 return false;
919 }
920
921 /** determine window page scroll amount */
GetWinPagesScrollAmount(const sal_Int16 _nWinPagesToScroll) const922 SwTwips SwPagePreviewLayout::GetWinPagesScrollAmount(
923 const sal_Int16 _nWinPagesToScroll ) const
924 {
925 SwTwips nScrollAmount;
926 if ( mbDoesLayoutRowsFitIntoWindow )
927 {
928 nScrollAmount = (mnPreviewLayoutHeight - gnYFree) * _nWinPagesToScroll;
929 }
930 else
931 nScrollAmount = _nWinPagesToScroll * maPaintedPreviewDocRect.GetHeight();
932
933 // check, if preview layout size values are valid.
934 // If not, the checks for an adjustment of the scroll amount aren't useful.
935 if ( mbLayoutSizesValid )
936 {
937 if ( (maPaintedPreviewDocRect.Top() + nScrollAmount) <= 0 )
938 nScrollAmount = -maPaintedPreviewDocRect.Top();
939
940 // correct scroll amount
941 if ( nScrollAmount > 0 &&
942 maPaintedPreviewDocRect.Bottom() == maPreviewDocRect.Bottom()
943 )
944 {
945 nScrollAmount = 0;
946 }
947 else
948 {
949 while ( (maPaintedPreviewDocRect.Top() + nScrollAmount + gnYFree) >= maPreviewDocRect.GetHeight() )
950 {
951 nScrollAmount -= mnRowHeight;
952 }
953 }
954 }
955
956 return nScrollAmount;
957 }
958
959 // methods to paint page preview layout
960
961 namespace
962 {
963 /// Similar to RenderContextGuard, but does not touch the draw view.
964 class PreviewRenderContextGuard
965 {
966 VclPtr<vcl::RenderContext> m_pOriginalValue;
967 SwViewShell& m_rShell;
968
969 public:
PreviewRenderContextGuard(SwViewShell & rShell,vcl::RenderContext * pValue)970 PreviewRenderContextGuard(SwViewShell& rShell, vcl::RenderContext* pValue)
971 : m_pOriginalValue(rShell.GetOut()),
972 m_rShell(rShell)
973 {
974 m_rShell.SetOut(pValue);
975 }
976
~PreviewRenderContextGuard()977 ~PreviewRenderContextGuard()
978 {
979 m_rShell.SetOut(m_pOriginalValue);
980 }
981 };
982 }
983
984 /** paint prepared preview
985
986 */
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle & rOutRect) const987 bool SwPagePreviewLayout::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rOutRect) const
988 {
989 PreviewRenderContextGuard aGuard(mrParentViewShell, &rRenderContext);
990 // check environment and parameters
991 {
992 if (!mrParentViewShell.GetWin() && !mrParentViewShell.GetOut()->GetConnectMetaFile())
993 {
994 return false;
995 }
996
997 OSL_ENSURE(mbPaintInfoValid, "invalid preview settings - no paint of preview");
998 if (!mbPaintInfoValid)
999 return false;
1000 }
1001
1002 // OD 17.11.2003 #i22014# - no paint, if <superfluous> flag is set at layout
1003 if (mrLayoutRootFrame.IsSuperfluous())
1004 {
1005 return true;
1006 }
1007
1008 // environment and parameter ok
1009
1010 if (mbInPaint)
1011 {
1012 return false;
1013 }
1014 mbInPaint = true;
1015
1016 OutputDevice* pOutputDev = &rRenderContext;
1017
1018 // prepare paint
1019 if ( !maPreviewPages.empty() )
1020 {
1021 mrParentViewShell.Imp()->m_bFirstPageInvalid = false;
1022 mrParentViewShell.Imp()->m_pFirstVisiblePage =
1023 const_cast<SwPageFrame*>(maPreviewPages[0]->pPage);
1024 }
1025
1026 // paint preview background
1027 {
1028 SwRegionRects aPreviewBackgrdRegion(rOutRect);
1029 // calculate preview background rectangles
1030 for ( auto & rpPreviewPage : maPreviewPages )
1031 {
1032 if ( rpPreviewPage->bVisible )
1033 {
1034 aPreviewBackgrdRegion -=
1035 SwRect( rpPreviewPage->aPreviewWinPos, rpPreviewPage->aPageSize );
1036 }
1037 }
1038 // paint preview background rectangles
1039 mrParentViewShell.PaintDesktop_(aPreviewBackgrdRegion);
1040 }
1041
1042 // prepare data for paint of pages
1043 const tools::Rectangle aPxOutRect( pOutputDev->LogicToPixel(rOutRect) );
1044
1045 MapMode aMapMode( pOutputDev->GetMapMode() );
1046 MapMode aSavedMapMode = aMapMode;
1047
1048 const vcl::Font& rEmptyPgFont = SwPageFrame::GetEmptyPageFont();
1049
1050 for ( auto & rpPreviewPage : maPreviewPages )
1051 {
1052 if ( !rpPreviewPage->bVisible )
1053 continue;
1054
1055 tools::Rectangle aPageRect( rpPreviewPage->aLogicPos, rpPreviewPage->aPageSize );
1056 aMapMode.SetOrigin( rpPreviewPage->aMapOffset );
1057 pOutputDev->SetMapMode( aMapMode );
1058 tools::Rectangle aPxPaintRect = pOutputDev->LogicToPixel( aPageRect );
1059 if ( aPxOutRect.IsOver( aPxPaintRect) )
1060 {
1061 const SwPageFrame* pPage = rpPreviewPage->pPage;
1062
1063 if (pPage->IsEmptyPage())
1064 {
1065 const Color aRetouche( mrParentViewShell.Imp()->GetRetoucheColor() );
1066 if( pOutputDev->GetFillColor() != aRetouche )
1067 pOutputDev->SetFillColor( aRetouche );
1068 pOutputDev->SetLineColor(); // no line color
1069 // use aligned page rectangle
1070 {
1071 SwRect aTmpPageRect( aPageRect );
1072 ::SwAlignRect( aTmpPageRect, &mrParentViewShell, &rRenderContext );
1073 aPageRect = aTmpPageRect.SVRect();
1074 }
1075 pOutputDev->DrawRect( aPageRect );
1076
1077 // paint empty page text
1078 vcl::Font aOldFont( pOutputDev->GetFont() );
1079 pOutputDev->SetFont( rEmptyPgFont );
1080 pOutputDev->DrawText( aPageRect, SwResId( STR_EMPTYPAGE ),
1081 DrawTextFlags::VCenter |
1082 DrawTextFlags::Center |
1083 DrawTextFlags::Clip );
1084 pOutputDev->SetFont( aOldFont );
1085 // paint shadow and border for empty page
1086 // use new method to paint page border and shadow
1087 SwPageFrame::PaintBorderAndShadow( aPageRect, &mrParentViewShell, true, false, true );
1088 }
1089 else
1090 {
1091 const bool bIsLeftShadowed = pPage->IsLeftShadowNeeded();
1092 const bool bIsRightShadowed = pPage->IsRightShadowNeeded();
1093
1094 mrParentViewShell.maVisArea = aPageRect;
1095 aPxPaintRect.Intersection( aPxOutRect );
1096 tools::Rectangle aPaintRect = pOutputDev->PixelToLogic( aPxPaintRect );
1097 mrParentViewShell.Paint(rRenderContext, aPaintRect);
1098
1099 // --> OD 2007-08-15 #i80691#
1100 // paint page border and shadow
1101 {
1102 SwRect aPageBorderRect;
1103 SwPageFrame::GetBorderAndShadowBoundRect( SwRect( aPageRect ), &mrParentViewShell, &rRenderContext, aPageBorderRect,
1104 bIsLeftShadowed, bIsRightShadowed, true );
1105 const vcl::Region aDLRegion(aPageBorderRect.SVRect());
1106 mrParentViewShell.DLPrePaint2(aDLRegion);
1107 SwPageFrame::PaintBorderAndShadow( aPageRect, &mrParentViewShell, true, false, true );
1108 mrParentViewShell.DLPostPaint2(true);
1109 }
1110 // <--
1111 }
1112 // OD 07.11.2003 #i22014# - stop painting, because new print
1113 // preview layout is created during paint.
1114 if ( mbNewLayoutDuringPaint )
1115 {
1116 break;
1117 }
1118
1119 if (pPage->GetPhyPageNum() == mnSelectedPageNum)
1120 {
1121 PaintSelectMarkAtPage(rRenderContext, rpPreviewPage.get());
1122 }
1123 }
1124 }
1125
1126 // OD 17.11.2003 #i22014# - no update of accessible preview, if a new
1127 // print preview layout is created during paint.
1128 if ( !mbNewLayoutDuringPaint )
1129 {
1130 // update at accessibility interface
1131 mrParentViewShell.Imp()->UpdateAccessiblePreview(
1132 maPreviewPages,
1133 aMapMode.GetScaleX(),
1134 mrLayoutRootFrame.GetPageByPageNum( mnSelectedPageNum ),
1135 maWinSize );
1136 }
1137
1138 pOutputDev->SetMapMode( aSavedMapMode );
1139 mrParentViewShell.maVisArea.Clear();
1140
1141 // OD 07.11.2003 #i22014#
1142 mbInPaint = false;
1143 mbNewLayoutDuringPaint = false;
1144
1145 return true;
1146 }
1147
1148 /** repaint pages on page preview
1149
1150 OD 18.12.2002 #103492#
1151 */
Repaint(const tools::Rectangle & rInvalidCoreRect) const1152 void SwPagePreviewLayout::Repaint( const tools::Rectangle& rInvalidCoreRect ) const
1153 {
1154 // check environment and parameters
1155 {
1156 if ( !mrParentViewShell.GetWin() &&
1157 !mrParentViewShell.GetOut()->GetConnectMetaFile() )
1158 return;
1159
1160 OSL_ENSURE( mbPaintInfoValid,
1161 "invalid preview settings - no paint of preview" );
1162 if ( !mbPaintInfoValid )
1163 return;
1164 }
1165
1166 // environment and parameter ok
1167
1168 // prepare paint
1169 if ( !maPreviewPages.empty() )
1170 {
1171 mrParentViewShell.Imp()->m_bFirstPageInvalid = false;
1172 mrParentViewShell.Imp()->m_pFirstVisiblePage =
1173 const_cast<SwPageFrame*>(maPreviewPages[0]->pPage);
1174 }
1175
1176 // invalidate visible pages, which overlap the invalid core rectangle
1177 for ( auto & rpPreviewPage : maPreviewPages )
1178 {
1179 if ( !rpPreviewPage->bVisible )
1180 continue;
1181
1182 tools::Rectangle aPageRect( rpPreviewPage->aLogicPos, rpPreviewPage->aPageSize );
1183 if ( rInvalidCoreRect.IsOver( aPageRect ) )
1184 {
1185 aPageRect.Intersection(rInvalidCoreRect);
1186 tools::Rectangle aInvalidPreviewRect = aPageRect;
1187 aInvalidPreviewRect.SetPos( aInvalidPreviewRect.TopLeft() -
1188 rpPreviewPage->aLogicPos +
1189 rpPreviewPage->aPreviewWinPos );
1190 mrParentViewShell.GetWin()->Invalidate( aInvalidPreviewRect );
1191 }
1192 }
1193 }
1194
1195 /** paint selection mark at page
1196
1197 OD 17.12.2002 #103492#
1198 */
PaintSelectMarkAtPage(vcl::RenderContext & rRenderContext,const PreviewPage * _aSelectedPreviewPage) const1199 void SwPagePreviewLayout::PaintSelectMarkAtPage(vcl::RenderContext& rRenderContext,
1200 const PreviewPage* _aSelectedPreviewPage ) const
1201 {
1202 OutputDevice* pOutputDev = &rRenderContext;
1203 MapMode aMapMode( pOutputDev->GetMapMode() );
1204 // save mapping mode of output device
1205 MapMode aSavedMapMode = aMapMode;
1206 // save fill and line color of output device
1207 Color aFill( pOutputDev->GetFillColor() );
1208 Color aLine( pOutputDev->GetLineColor() );
1209
1210 // determine selection mark color
1211 Color aSelPgLineColor(COL_LIGHTBLUE);
1212 const StyleSettings& rSettings =
1213 mrParentViewShell.GetWin()->GetSettings().GetStyleSettings();
1214 if ( rSettings.GetHighContrastMode() )
1215 aSelPgLineColor = rSettings.GetHighlightTextColor();
1216
1217 // set needed mapping mode at output device
1218 aMapMode.SetOrigin( _aSelectedPreviewPage->aMapOffset );
1219 pOutputDev->SetMapMode( aMapMode );
1220
1221 // calculate page rectangle in pixel coordinates
1222 SwRect aPageRect( _aSelectedPreviewPage->aLogicPos,
1223 _aSelectedPreviewPage->aPageSize );
1224 // OD 19.02.2003 #107369# - use aligned page rectangle, as it is used for
1225 // page border and shadow paint - see <SwPageFrame::PaintBorderAndShadow(..)>
1226 ::SwAlignRect( aPageRect, &mrParentViewShell, pOutputDev );
1227 tools::Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1228
1229 // draw two rectangle
1230 // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1231 tools::Rectangle aRect( aPxPageRect.Left(), aPxPageRect.Top(),
1232 aPxPageRect.Right(), aPxPageRect.Bottom() );
1233 aRect = pOutputDev->PixelToLogic( aRect );
1234 pOutputDev->SetFillColor(); // OD 20.02.2003 #107369# - no fill color
1235 pOutputDev->SetLineColor( aSelPgLineColor );
1236 pOutputDev->DrawRect( aRect );
1237 // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1238 aRect = tools::Rectangle( aPxPageRect.Left()+1, aPxPageRect.Top()+1,
1239 aPxPageRect.Right()-1, aPxPageRect.Bottom()-1 );
1240 aRect = pOutputDev->PixelToLogic( aRect );
1241 pOutputDev->DrawRect( aRect );
1242
1243 // reset fill and line color of output device
1244 pOutputDev->SetFillColor( aFill );
1245 pOutputDev->SetLineColor( aLine );
1246
1247 // reset mapping mode of output device
1248 pOutputDev->SetMapMode( aSavedMapMode );
1249 }
1250
1251 /** paint to mark new selected page
1252
1253 OD 17.12.2002 #103492#
1254 Perform paint for current selected page in order to unmark it.
1255 Set new selected page and perform paint to mark this page.
1256
1257 @note _nSelectedPage, mnSelectedPage are absolute
1258 */
MarkNewSelectedPage(const sal_uInt16 _nSelectedPage)1259 void SwPagePreviewLayout::MarkNewSelectedPage( const sal_uInt16 _nSelectedPage )
1260 {
1261 const sal_uInt16 nOldSelectedPageNum = mnSelectedPageNum;
1262 mnSelectedPageNum = _nSelectedPage;
1263
1264 // re-paint for current selected page in order to unmark it.
1265 const PreviewPage* pOldSelectedPreviewPage = GetPreviewPageByPageNum( nOldSelectedPageNum );
1266 OutputDevice* pOutputDev = mrParentViewShell.GetOut();
1267 if ( pOldSelectedPreviewPage && pOldSelectedPreviewPage->bVisible )
1268 {
1269 // OD 20.02.2003 #107369# - invalidate only areas of selection mark.
1270 SwRect aPageRect( pOldSelectedPreviewPage->aPreviewWinPos,
1271 pOldSelectedPreviewPage->aPageSize );
1272 ::SwAlignRect( aPageRect, &mrParentViewShell, pOutputDev );
1273 tools::Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1274 // invalidate top mark line
1275 tools::Rectangle aInvalPxRect( aPxPageRect.Left(), aPxPageRect.Top(),
1276 aPxPageRect.Right(), aPxPageRect.Top()+1 );
1277 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1278 // invalidate right mark line
1279 aInvalPxRect = tools::Rectangle( aPxPageRect.Right()-1, aPxPageRect.Top(),
1280 aPxPageRect.Right(), aPxPageRect.Bottom() );
1281 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1282 // invalidate bottom mark line
1283 aInvalPxRect = tools::Rectangle( aPxPageRect.Left(), aPxPageRect.Bottom()-1,
1284 aPxPageRect.Right(), aPxPageRect.Bottom() );
1285 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1286 // invalidate left mark line
1287 aInvalPxRect = tools::Rectangle( aPxPageRect.Left(), aPxPageRect.Top(),
1288 aPxPageRect.Left()+1, aPxPageRect.Bottom() );
1289 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1290 }
1291
1292 // re-paint for new selected page in order to mark it.
1293 const PreviewPage* pNewSelectedPreviewPage = GetPreviewPageByPageNum( _nSelectedPage );
1294 if ( pNewSelectedPreviewPage && pNewSelectedPreviewPage->bVisible )
1295 {
1296 const PreviewPage* pSelectedPreviewPage = GetPreviewPageByPageNum(mnSelectedPageNum);
1297 SwRect aPageRect(pSelectedPreviewPage->aPreviewWinPos, pSelectedPreviewPage->aPageSize);
1298 ::SwAlignRect(aPageRect, &mrParentViewShell, pOutputDev);
1299 mrParentViewShell.GetWin()->Invalidate(aPageRect.SVRect());
1300 }
1301 }
1302
1303 // helper methods
1304
1305 /** get preview page by physical page number
1306
1307 OD 17.12.2002 #103492#
1308 */
1309 struct EqualsPageNumPred
1310 {
1311 const sal_uInt16 mnPageNum;
EqualsPageNumPredEqualsPageNumPred1312 explicit EqualsPageNumPred(const sal_uInt16 _nPageNum)
1313 : mnPageNum( _nPageNum )
1314 {}
operator ()EqualsPageNumPred1315 bool operator() ( const std::unique_ptr<PreviewPage> & _pPreviewPage )
1316 {
1317 return _pPreviewPage->pPage->GetPhyPageNum() == mnPageNum;
1318 }
1319 };
1320
GetPreviewPageByPageNum(const sal_uInt16 _nPageNum) const1321 const PreviewPage* SwPagePreviewLayout::GetPreviewPageByPageNum( const sal_uInt16 _nPageNum ) const
1322 {
1323 auto aFoundPreviewPageIter =
1324 std::find_if( maPreviewPages.begin(), maPreviewPages.end(),
1325 EqualsPageNumPred( _nPageNum ) );
1326
1327 if ( aFoundPreviewPageIter == maPreviewPages.end() )
1328 return nullptr;
1329
1330 return aFoundPreviewPageIter->get();
1331 }
1332
1333 /** determine row the page with the given number is in
1334
1335 OD 17.01.2003 #103492#
1336
1337 @note _nPageNum is relative
1338 */
GetRowOfPage(sal_uInt16 _nPageNum) const1339 sal_uInt16 SwPagePreviewLayout::GetRowOfPage( sal_uInt16 _nPageNum ) const
1340 {
1341 // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1342 // by <mbBookPreview>.
1343 if ( mbBookPreview )
1344 {
1345 // Note: increase given physical page number by one, because left-top-corner
1346 // in the preview layout is left blank.
1347 ++_nPageNum;
1348 }
1349
1350 return _nPageNum / mnCols + ((_nPageNum % mnCols)>0 ? 1 : 0);
1351 }
1352
1353 /** determine column the page with the given number is in
1354
1355 OD 17.01.2003 #103492#
1356
1357 @note _nPageNum is relative
1358 */
GetColOfPage(sal_uInt16 _nPageNum) const1359 sal_uInt16 SwPagePreviewLayout::GetColOfPage( sal_uInt16 _nPageNum ) const
1360 {
1361 // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1362 // by <mbBookPreview>.
1363 if ( mbBookPreview )
1364 {
1365 // Note: increase given physical page number by one, because left-top-corner
1366 // in the preview layout is left blank.
1367 ++_nPageNum;
1368 }
1369
1370 const sal_uInt16 nCol = _nPageNum % mnCols;
1371 return nCol ? nCol : mnCols;
1372 }
1373
GetPreviewDocSize() const1374 Size SwPagePreviewLayout::GetPreviewDocSize() const
1375 {
1376 OSL_ENSURE( PreviewLayoutValid(), "PagePreviewLayout not valid" );
1377 return maPreviewDocRect.GetSize();
1378 }
1379
1380 /** get size of a preview page by its physical page number
1381
1382 OD 15.01.2003 #103492#
1383 */
GetPreviewPageSizeByPageNum(sal_uInt16 _nPageNum) const1384 Size SwPagePreviewLayout::GetPreviewPageSizeByPageNum( sal_uInt16 _nPageNum ) const
1385 {
1386 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
1387 if ( pPreviewPage )
1388 {
1389 return pPreviewPage->aPageSize;
1390 }
1391 return Size( 0, 0 );
1392 }
1393
1394 /** get virtual page number by its physical page number
1395
1396 OD 21.03.2003 #108282#
1397 */
GetVirtPageNumByPageNum(sal_uInt16 _nPageNum) const1398 sal_uInt16 SwPagePreviewLayout::GetVirtPageNumByPageNum( sal_uInt16 _nPageNum ) const
1399 {
1400 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
1401 if ( pPreviewPage )
1402 {
1403 return pPreviewPage->pPage->GetVirtPageNum();
1404 }
1405 return 0;
1406 }
1407
1408 /** Convert absolute to relative page numbers (see PrintEmptyPages) */
ConvertAbsoluteToRelativePageNum(sal_uInt16 _nAbsPageNum) const1409 sal_uInt16 SwPagePreviewLayout::ConvertAbsoluteToRelativePageNum( sal_uInt16 _nAbsPageNum ) const
1410 {
1411 if ( mbBookPreview || mbPrintEmptyPages || !_nAbsPageNum )
1412 {
1413 return _nAbsPageNum;
1414 }
1415
1416 const SwPageFrame* pTmpPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
1417
1418 sal_uInt16 nRet = 1;
1419
1420 while ( pTmpPage && pTmpPage->GetPhyPageNum() != _nAbsPageNum )
1421 {
1422 if ( !pTmpPage->IsEmptyPage() )
1423 ++nRet;
1424
1425 pTmpPage = static_cast<const SwPageFrame*>( pTmpPage->GetNext() );
1426 }
1427
1428 return nRet;
1429 }
1430
1431 /** Convert relative to absolute page numbers (see PrintEmptyPages) */
ConvertRelativeToAbsolutePageNum(sal_uInt16 _nRelPageNum) const1432 sal_uInt16 SwPagePreviewLayout::ConvertRelativeToAbsolutePageNum( sal_uInt16 _nRelPageNum ) const
1433 {
1434 if ( mbBookPreview || mbPrintEmptyPages || !_nRelPageNum )
1435 {
1436 return _nRelPageNum;
1437 }
1438
1439 const SwPageFrame* pTmpPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
1440 const SwPageFrame* pRet = nullptr;
1441
1442 sal_uInt16 i = 0;
1443 while( pTmpPage && i != _nRelPageNum )
1444 {
1445 if ( !pTmpPage->IsEmptyPage() )
1446 ++i;
1447
1448 pRet = pTmpPage;
1449 pTmpPage = static_cast<const SwPageFrame*>( pTmpPage->GetNext() );
1450 }
1451
1452 return pRet->GetPhyPageNum();
1453 }
1454
1455 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1456