xref: /trunk/main/sw/source/core/view/pagepreviewlayout.cxx (revision 20a4bcff3806011e555ba114deeec0a8e4a5f048)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_sw.hxx"
24 #include <pagepreviewlayout.hxx>
25 #ifndef _PREVWPAGE_HXX
26 #include <prevwpage.hxx>
27 #endif
28 
29 #include <algorithm>
30 #include <vcl/window.hxx>
31 #include <rootfrm.hxx>
32 #include <pagefrm.hxx>
33 #include <viewsh.hxx>
34 #include <viewimp.hxx>
35 #include <viewopt.hxx>
36 #include <swregion.hxx>
37 #ifndef _COMCORE_HRC
38 #include <comcore.hrc>
39 #endif
40 // OD 19.02.2003 #107369# - method <SwAlignRect(..)>
41 #include <frmtool.hxx>
42 // OD 24.09.2003 #i19975#
43 #include <svx/zoomitem.hxx>
44 #include <printdata.hxx>
45 
46 #include <IDocumentDeviceAccess.hxx>
47 
48 // OD 20.02.2003 #107369# - method to update statics for paint
49 // Note: method defined in '/sw/source/core/layout/paintfrm.cxx'
50 extern void SwCalcPixStatics( OutputDevice *pOut );
51 
52 // =============================================================================
53 // methods to initialize page preview layout
54 // =============================================================================
55 SwPagePreviewLayout::SwPagePreviewLayout( ViewShell& _rParentViewShell,
56                                           const SwRootFrm& _rLayoutRootFrm )
57     : mnXFree ( 3 * 142 ),
58       mnYFree ( 3 * 142 ),
59       mrParentViewShell( _rParentViewShell ),
60       mrLayoutRootFrm ( _rLayoutRootFrm )
61 {
62     _Clear();
63 
64     // OD 2004-03-05 #i18143#
65     mbBookPreview = false;
66     mbBookPreviewModeToggled = false;
67 
68     mbPrintEmptyPages = mrParentViewShell.getIDocumentDeviceAccess()->getPrintData().IsPrintEmptyPages();
69 }
70 
71 void SwPagePreviewLayout::_Clear()
72 {
73     mbLayoutInfoValid = mbLayoutSizesValid = mbPaintInfoValid = false;
74 
75     maWinSize.Width() = 0;
76     maWinSize.Height() = 0;
77     mnCols = mnRows = 0;
78 
79     _ClearPrevwLayoutSizes();
80 
81     mbDoesLayoutRowsFitIntoWindow = false;
82     mbDoesLayoutColsFitIntoWindow = false;
83 
84     mnPaintPhyStartPageNum = 0;
85     mnPaintStartCol = mnPaintStartRow = 0;
86     mbNoPageVisible = false;
87     maPaintStartPageOffset.X() = 0;
88     maPaintStartPageOffset.Y() = 0;
89     maPaintPreviewDocOffset.X() = 0;
90     maPaintPreviewDocOffset.Y() = 0;
91     maAdditionalPaintOffset.X() = 0;
92     maAdditionalPaintOffset.Y() = 0;
93     maPaintedPrevwDocRect.Left() = 0;
94     maPaintedPrevwDocRect.Top() = 0;
95     maPaintedPrevwDocRect.Right() = 0;
96     maPaintedPrevwDocRect.Bottom() = 0;
97     mnSelectedPageNum = 0;
98     _ClearPrevwPageData();
99 
100     // OD 07.11.2003 #i22014#
101     mbInPaint = false;
102     mbNewLayoutDuringPaint = false;
103 }
104 
105 void SwPagePreviewLayout::_ClearPrevwLayoutSizes()
106 {
107     mnPages = 0;
108 
109     maMaxPageSize.Width() = 0;
110     maMaxPageSize.Height() = 0;
111     maPreviewDocRect.Left() = maPreviewDocRect.Top() = 0;
112     maPreviewDocRect.Right() = maPreviewDocRect.Bottom() = 0;
113     mnColWidth = mnRowHeight = 0;
114     mnPrevwLayoutWidth = mnPrevwLayoutHeight = 0;
115 }
116 
117 void SwPagePreviewLayout::_ClearPrevwPageData()
118 {
119     for ( std::vector<PrevwPage*>::iterator aPageDelIter = maPrevwPages.begin();
120         aPageDelIter != maPrevwPages.end();
121         ++aPageDelIter )
122     {
123         delete (*aPageDelIter);
124     }
125     maPrevwPages.clear();
126 }
127 
128 /** calculate page preview layout sizes
129 
130     OD 18.12.2002 #103492#
131 
132     @author OD
133 */
134 void SwPagePreviewLayout::_CalcPrevwLayoutSizes()
135 {
136     // calculate maximal page size; calculate also number of pages
137 
138     const SwPageFrm* pPage = static_cast<const SwPageFrm*>(mrLayoutRootFrm.Lower());
139     while ( pPage )
140     {
141         if ( !mbBookPreview && !mbPrintEmptyPages && pPage->IsEmptyPage() )
142         {
143             pPage = static_cast<const SwPageFrm*>(pPage->GetNext());
144             continue;
145         }
146 
147         ++mnPages;
148         pPage->Calc();
149         const Size& rPageSize = pPage->Frm().SSize();
150         if ( rPageSize.Width() > maMaxPageSize.Width() )
151             maMaxPageSize.Width() = rPageSize.Width();
152         if ( rPageSize.Height() > maMaxPageSize.Height() )
153             maMaxPageSize.Height() = rPageSize.Height();
154         pPage = static_cast<const SwPageFrm*>(pPage->GetNext());
155     }
156     // calculate and set column width and row height
157     mnColWidth = maMaxPageSize.Width() + mnXFree;
158     mnRowHeight = maMaxPageSize.Height() + mnYFree;
159 
160     // calculate and set preview layout width and height
161     mnPrevwLayoutWidth = mnCols * mnColWidth + mnXFree;
162     mnPrevwLayoutHeight = mnRows * mnRowHeight + mnYFree;
163 
164     // calculate document rectangle in preview layout
165     {
166         Size aDocSize;
167         // document width
168         aDocSize.Width() = mnPrevwLayoutWidth;
169 
170         // document height
171         // determine number of rows needed for <nPages> in preview layout
172         // OD 19.02.2003 #107369# - use method <GetRowOfPage(..)>.
173         sal_uInt16 nDocRows = GetRowOfPage( mnPages );
174         aDocSize.Height() = nDocRows * maMaxPageSize.Height() + (nDocRows+1) * mnYFree;
175         maPreviewDocRect.SetPos( Point( 0, 0 ) );
176         maPreviewDocRect.SetSize( aDocSize );
177     }
178 }
179 
180 /** init page preview layout
181 
182     OD 11.12.2002 #103492#
183     initialize the page preview settings for a given layout.
184     side effects:
185     (1) If parameter <_bCalcScale> is true, mapping mode with calculated
186     scaling is set at the output device and the zoom at the view options of
187     the given view shell is set with the calculated scaling.
188 
189     @author OD
190 */
191 bool SwPagePreviewLayout::Init( const sal_uInt16 _nCols,
192                                 const sal_uInt16 _nRows,
193                                 const Size&      _rPxWinSize,
194                                 const bool       _bCalcScale
195                               )
196 {
197     // check environment and parameters
198     {
199         bool bColsRowsValid = (_nCols != 0) && (_nRows != 0);
200         ASSERT( bColsRowsValid, "preview layout parameters not correct - preview layout can *not* be initialized" );
201         if ( !bColsRowsValid )
202             return false;
203 
204         bool bPxWinSizeValid = (_rPxWinSize.Width() >= 0) &&
205                                (_rPxWinSize.Height() >= 0);
206         ASSERT( bPxWinSizeValid, "no window size - preview layout can *not* be initialized" );
207         if ( !bPxWinSizeValid )
208             return false;
209     }
210 
211     // environment and parameters OK
212 
213     // clear existing preview settings
214     _Clear();
215 
216     // set layout information columns and rows
217     mnCols = _nCols;
218     mnRows = _nRows;
219 
220     _CalcPrevwLayoutSizes();
221 
222     // validate layout information
223     mbLayoutInfoValid = true;
224 
225     if ( _bCalcScale )
226     {
227         // calculate scaling
228         MapMode aMapMode( MAP_TWIP );
229         Size aWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize, aMapMode );
230         Fraction aXScale( aWinSize.Width(), mnPrevwLayoutWidth );
231         Fraction aYScale( aWinSize.Height(), mnPrevwLayoutHeight );
232         if( aXScale < aYScale )
233             aYScale = aXScale;
234         {
235             // adjust scaling for Drawing layer.
236             aYScale *= Fraction( 1000, 1 );
237             long nNewNuminator = aYScale.operator long();
238             if( nNewNuminator < 1 )
239                 nNewNuminator = 1;
240             aYScale = Fraction( nNewNuminator, 1000 );
241             // propagate scaling as zoom percentage to view options for font cache
242             _ApplyNewZoomAtViewShell( static_cast<sal_uInt8>(nNewNuminator/10) );
243         }
244         aMapMode.SetScaleY( aYScale );
245         aMapMode.SetScaleX( aYScale );
246         // set created mapping mode with calculated scaling at output device.
247         mrParentViewShell.GetOut()->SetMapMode( aMapMode );
248         // OD 20.02.2003 #107369# - update statics for paint.
249         ::SwCalcPixStatics( mrParentViewShell.GetOut() );
250     }
251 
252     // set window size in twips
253     maWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize );
254     // validate layout sizes
255     mbLayoutSizesValid = true;
256 
257     return true;
258 }
259 
260 /** apply new zoom at given view shell
261 
262     OD 11.12.2002 #103492# - implementation of <_ApplyNewZoomAtViewShell>
263 
264     @author OD
265 */
266 void SwPagePreviewLayout::_ApplyNewZoomAtViewShell( sal_uInt8 _aNewZoom )
267 {
268     SwViewOption aNewViewOptions = *(mrParentViewShell.GetViewOptions());
269     if ( aNewViewOptions.GetZoom() != _aNewZoom )
270     {
271         aNewViewOptions.SetZoom( _aNewZoom );
272         // OD 24.09.2003 #i19975# - consider zoom type.
273         enum SvxZoomType eZoomType = SVX_ZOOM_PERCENT;
274         aNewViewOptions.SetZoomType( eZoomType );
275         mrParentViewShell.ApplyViewOptions( aNewViewOptions );
276     }
277 }
278 
279 /** method to adjust page preview layout to document changes
280 
281     OD 18.12.2002 #103492#
282 
283     @author OD
284 */
285 bool SwPagePreviewLayout::ReInit()
286 {
287     // check environment and parameters
288     {
289         bool bLayoutSettingsValid = mbLayoutInfoValid && mbLayoutSizesValid;
290         ASSERT( bLayoutSettingsValid,
291                 "no valid preview layout info/sizes - no re-init of page preview layout");
292         if ( !bLayoutSettingsValid )
293             return false;
294     }
295 
296     _ClearPrevwLayoutSizes();
297     _CalcPrevwLayoutSizes();
298 
299     return true;
300 }
301 
302 // =============================================================================
303 // methods to prepare paint of page preview
304 // =============================================================================
305 /** prepare paint of page preview
306 
307     OD 12.12.2002 #103492#
308     OD 21.03.2003 #108282# - delete parameter _onStartPageVirtNum
309 
310     @author OD, _nProposedStartPageNum, _onStartPageNum are absolute
311 */
312 bool SwPagePreviewLayout::Prepare( const sal_uInt16 _nProposedStartPageNum,
313                                    const Point      _aProposedStartPos,
314                                    const Size&      _rPxWinSize,
315                                    sal_uInt16&      _onStartPageNum,
316                                    Rectangle&       _orDocPreviewPaintRect,
317                                    const bool       _bStartWithPageAtFirstCol
318                                  )
319 {
320     sal_uInt16 nProposedStartPageNum = ConvertAbsoluteToRelativePageNum( _nProposedStartPageNum );
321     // check environment and parameters
322     {
323         bool bLayoutSettingsValid = mbLayoutInfoValid && mbLayoutSizesValid;
324         ASSERT( bLayoutSettingsValid,
325                 "no valid preview layout info/sizes - no prepare of preview paint");
326         if ( !bLayoutSettingsValid )
327             return false;
328 
329         bool bStartPageRangeValid = nProposedStartPageNum <= mnPages;
330         ASSERT( bStartPageRangeValid,
331                 "proposed start page not existing - no prepare of preview paint");
332         if ( !bStartPageRangeValid )
333             return false;
334 
335         bool bStartPosRangeValid =
336                 _aProposedStartPos.X() >= 0 && _aProposedStartPos.Y() >= 0 &&
337                 _aProposedStartPos.X() <= maPreviewDocRect.Right() &&
338                 _aProposedStartPos.Y() <= maPreviewDocRect.Bottom();
339         ASSERT( bStartPosRangeValid,
340                 "proposed start position out of range - no prepare of preview paint");
341         if ( !bStartPosRangeValid )
342             return false;
343 
344         bool bWinSizeValid = _rPxWinSize.Width() != 0 && _rPxWinSize.Height() != 0;
345         ASSERT ( bWinSizeValid, "no window size - no prepare of preview paint");
346         if ( !bWinSizeValid )
347             return false;
348 
349         bool bStartInfoValid = _nProposedStartPageNum > 0 ||
350                                _aProposedStartPos != Point(0,0);
351         if ( !bStartInfoValid )
352             nProposedStartPageNum = 1;
353     }
354 
355     // environment and parameter OK
356 
357     // update window size at preview setting data
358     maWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize );
359 
360     mbNoPageVisible = false;
361     if ( nProposedStartPageNum > 0 )
362     {
363         // determine column and row of proposed start page in virtual preview layout
364         sal_uInt16 nColOfProposed = GetColOfPage( nProposedStartPageNum );
365         sal_uInt16 nRowOfProposed = GetRowOfPage( nProposedStartPageNum );
366         // determine start page
367         if ( _bStartWithPageAtFirstCol )
368         {
369             // OD 19.02.2003 #107369# - leaving left-top-corner blank is
370             // controlled by <mbBookPreview>.
371             if ( mbBookPreview &&
372                  ( nProposedStartPageNum == 1 || nRowOfProposed == 1 )
373                )
374                 mnPaintPhyStartPageNum = 1;
375             else
376                 mnPaintPhyStartPageNum = nProposedStartPageNum - (nColOfProposed-1);
377         }
378         else
379             mnPaintPhyStartPageNum = nProposedStartPageNum;
380 
381         mnPaintPhyStartPageNum = ConvertRelativeToAbsolutePageNum( mnPaintPhyStartPageNum );
382 
383         // set starting column
384         if ( _bStartWithPageAtFirstCol )
385             mnPaintStartCol = 1;
386         else
387             mnPaintStartCol = nColOfProposed;
388         // set starting row
389         mnPaintStartRow = nRowOfProposed;
390         // page offset == (-1,-1), indicating no offset and paint of free space.
391         maPaintStartPageOffset.X() = -1;
392         maPaintStartPageOffset.Y() = -1;
393         // virtual preview document offset.
394         if ( _bStartWithPageAtFirstCol )
395             maPaintPreviewDocOffset.X() = 0;
396         else
397             maPaintPreviewDocOffset.X() = (nColOfProposed-1) * mnColWidth;
398         maPaintPreviewDocOffset.Y() = (nRowOfProposed-1) * mnRowHeight;
399     }
400     else
401     {
402         // determine column and row of proposed start position.
403         // Note: paint starts at point (0,0)
404         sal_uInt16 nColOfProposed =
405                 static_cast<sal_uInt16>(_aProposedStartPos.X() / mnColWidth) + 1;
406         sal_uInt16 nRowOfProposed =
407                 static_cast<sal_uInt16>(_aProposedStartPos.Y() / mnRowHeight) + 1;
408         // determine start page == page at proposed start position
409         // OD 19.02.2003 #107369# - leaving left-top-corner blank is
410         // controlled by <mbBookPreview>.
411         if ( mbBookPreview &&
412              ( nRowOfProposed == 1 && nColOfProposed == 1 )
413            )
414             mnPaintPhyStartPageNum = 1;
415         else
416         {
417             // OD 19.02.2003 #107369# - leaving left-top-corner blank is
418             // controlled by <mbBookPreview>.
419             mnPaintPhyStartPageNum = (nRowOfProposed-1) * mnCols + nColOfProposed;
420             if ( mbBookPreview )
421                  --mnPaintPhyStartPageNum;
422             if ( mnPaintPhyStartPageNum > mnPages )
423             {
424                 // no page will be visible, because shown part of document
425                 // preview is the last row to the right of the last page
426                 mnPaintPhyStartPageNum = mnPages;
427                 mbNoPageVisible = true;
428             }
429         }
430         // set starting column and starting row
431         mnPaintStartCol = nColOfProposed;
432         mnPaintStartRow = nRowOfProposed;
433         // page offset
434         maPaintStartPageOffset.X() =
435                 (_aProposedStartPos.X() % mnColWidth) - mnXFree;
436         maPaintStartPageOffset.Y() =
437                 (_aProposedStartPos.Y() % mnRowHeight) - mnYFree;
438         // virtual preview document offset.
439         maPaintPreviewDocOffset = _aProposedStartPos;
440     }
441 
442     // determine additional paint offset, if preview layout fits into window.
443     _CalcAdditionalPaintOffset();
444 
445     // determine rectangle to be painted from document preview
446     _CalcDocPrevwPaintRect();
447     _orDocPreviewPaintRect = maPaintedPrevwDocRect;
448 
449     // OD 20.01.2003 #103492# - shift visible preview document area to the left,
450     // if on the right is an area left blank.
451     if ( !mbDoesLayoutColsFitIntoWindow &&
452         maPaintedPrevwDocRect.GetWidth() < maWinSize.Width() )
453     {
454         maPaintedPrevwDocRect.Move(
455                 -(maWinSize.Width() - maPaintedPrevwDocRect.GetWidth()), 0 );
456         Prepare( 0, maPaintedPrevwDocRect.TopLeft(),
457                  _rPxWinSize, _onStartPageNum,
458                  _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
459     }
460 
461     // OD 20.01.2003 #103492# - shift visible preview document area to the top,
462     // if at the bottom is an area left blank.
463     if ( mbBookPreviewModeToggled &&
464          maPaintedPrevwDocRect.Bottom() == maPreviewDocRect.Bottom() &&
465          maPaintedPrevwDocRect.GetHeight() < maWinSize.Height() )
466     {
467         if ( mbDoesLayoutRowsFitIntoWindow )
468         {
469             if ( maPaintedPrevwDocRect.GetHeight() < mnPrevwLayoutHeight)
470             {
471                 maPaintedPrevwDocRect.Move(
472                         0, -(mnPrevwLayoutHeight - maPaintedPrevwDocRect.GetHeight()) );
473                 Prepare( 0, maPaintedPrevwDocRect.TopLeft(),
474                          _rPxWinSize, _onStartPageNum,
475                          _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
476             }
477         }
478         else
479         {
480             maPaintedPrevwDocRect.Move(
481                     0, -(maWinSize.Height() - maPaintedPrevwDocRect.GetHeight()) );
482             Prepare( 0, maPaintedPrevwDocRect.TopLeft(),
483                      _rPxWinSize, _onStartPageNum,
484                      _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
485         }
486     }
487 
488     // determine preview pages - visible pages with needed data for paint and
489     // accessible pages with needed data.
490     _CalcPreviewPages();
491 
492     // OD 07.11.2003 #i22014# - indicate new layout, if print preview is in paint
493     if ( mbInPaint )
494     {
495         mbNewLayoutDuringPaint = true;
496     }
497 
498     // validate paint data
499     mbPaintInfoValid = true;
500 
501     // return start page
502     _onStartPageNum = mnPaintPhyStartPageNum;
503 
504     return true;
505 }
506 
507 /** calculate additional paint offset
508 
509     OD 12.12.2002 #103492#
510 
511     @author OD
512 */
513 void SwPagePreviewLayout::_CalcAdditionalPaintOffset()
514 {
515     if ( mnPrevwLayoutWidth <= maWinSize.Width() &&
516         maPaintStartPageOffset.X() <= 0 )
517     {
518         mbDoesLayoutColsFitIntoWindow = true;
519         maAdditionalPaintOffset.X() = (maWinSize.Width() - mnPrevwLayoutWidth) / 2;
520     }
521     else
522     {
523         mbDoesLayoutColsFitIntoWindow = false;
524         maAdditionalPaintOffset.X() = 0;
525     }
526 
527     if ( mnPrevwLayoutHeight <= maWinSize.Height() &&
528         maPaintStartPageOffset.Y() <= 0 )
529     {
530         mbDoesLayoutRowsFitIntoWindow = true;
531         maAdditionalPaintOffset.Y() = (maWinSize.Height() - mnPrevwLayoutHeight) / 2;
532     }
533     else
534     {
535         mbDoesLayoutRowsFitIntoWindow = false;
536         maAdditionalPaintOffset.Y() = 0;
537     }
538 }
539 
540 /** calculate painted preview document rectangle
541 
542     OD 12.12.2002 #103492#
543 
544     @author OD
545 */
546 void SwPagePreviewLayout::_CalcDocPrevwPaintRect()
547 {
548     Point aTopLeftPos = maPaintPreviewDocOffset;
549     maPaintedPrevwDocRect.SetPos( aTopLeftPos );
550 
551     Size aSize;
552     if ( mbDoesLayoutColsFitIntoWindow )
553         //aSize.Width() = mnPrevwLayoutWidth;
554         aSize.Width() = Min( mnPrevwLayoutWidth,
555                              maPreviewDocRect.GetWidth() - aTopLeftPos.X() );
556     else
557         aSize.Width() = Min( maPreviewDocRect.GetWidth() - aTopLeftPos.X(),
558                              maWinSize.Width() - maAdditionalPaintOffset.X() );
559     if ( mbDoesLayoutRowsFitIntoWindow )
560         //aSize.Height() = mnPrevwLayoutHeight;
561         aSize.Height() = Min( mnPrevwLayoutHeight,
562                               maPreviewDocRect.GetHeight() - aTopLeftPos.Y() );
563     else
564         aSize.Height() = Min( maPreviewDocRect.GetHeight() - aTopLeftPos.Y(),
565                               maWinSize.Height() - maAdditionalPaintOffset.Y() );
566     maPaintedPrevwDocRect.SetSize( aSize );
567 }
568 
569 /** calculate preview pages
570 
571     OD 12.12.2002 #103492#
572 
573     @author OD
574 */
575 void SwPagePreviewLayout::_CalcPreviewPages()
576 {
577     _ClearPrevwPageData();
578 
579     if ( mbNoPageVisible )
580         return;
581 
582     // determine start page frame
583     const SwPageFrm* pStartPage = mrLayoutRootFrm.GetPageByPageNum( mnPaintPhyStartPageNum );
584 
585     // calculate initial paint offset
586     Point aInitialPaintOffset;
587     if ( maPaintStartPageOffset != Point( -1, -1 ) )
588         aInitialPaintOffset = Point(0,0) - maPaintStartPageOffset;
589     else
590         aInitialPaintOffset = Point( mnXFree, mnYFree );
591     aInitialPaintOffset += maAdditionalPaintOffset;
592 
593     // prepare loop data
594     const SwPageFrm* pPage = pStartPage;
595     sal_uInt16 nCurrCol = mnPaintStartCol;
596     sal_uInt16 nConsideredRows = 0;
597     Point aCurrPaintOffset = aInitialPaintOffset;
598     // loop on pages to determine preview background rectangles
599     while ( pPage &&
600             (!mbDoesLayoutRowsFitIntoWindow || nConsideredRows < mnRows) &&
601             aCurrPaintOffset.Y() < maWinSize.Height()
602           )
603     {
604         if ( !mbBookPreview && !mbPrintEmptyPages && pPage->IsEmptyPage() )
605         {
606             pPage = static_cast<const SwPageFrm*>(pPage->GetNext());
607             continue;
608         }
609 
610         pPage->Calc();
611 
612         // consider only pages, which have to be painted.
613         if ( nCurrCol < mnPaintStartCol )
614         {
615             // calculate data of invisible page needed for accessibility
616             PrevwPage* pPrevwPage = new PrevwPage;
617             Point aCurrAccOffset = aCurrPaintOffset -
618                             Point( (mnPaintStartCol-nCurrCol) * mnColWidth, 0 );
619             _CalcPreviewDataForPage( *(pPage), aCurrAccOffset, pPrevwPage );
620             pPrevwPage->bVisible = false;
621             maPrevwPages.push_back( pPrevwPage );
622             // continue with next page and next column
623             pPage = static_cast<const SwPageFrm*>(pPage->GetNext());
624             ++nCurrCol;
625             continue;
626         }
627         if ( aCurrPaintOffset.X() < maWinSize.Width() )
628         {
629             // OD 19.02.2003 #107369# - leaving left-top-corner blank is
630             // controlled by <mbBookPreview>.
631             if ( mbBookPreview && pPage->GetPhyPageNum() == 1 && mnCols != 1 && nCurrCol == 1 )
632             {
633                 // first page in 2nd column
634                 // --> continue with increased paint offset and next column
635                 aCurrPaintOffset.X() += mnColWidth;
636                 ++nCurrCol;
637                 continue;
638             }
639 
640             // calculate data of visible page
641             PrevwPage* pPrevwPage = new PrevwPage;
642             _CalcPreviewDataForPage( *(pPage), aCurrPaintOffset, pPrevwPage );
643             pPrevwPage->bVisible = true;
644             maPrevwPages.push_back( pPrevwPage );
645         }
646         else
647         {
648             // calculate data of invisible page needed for accessibility
649             PrevwPage* pPrevwPage = new PrevwPage;
650             _CalcPreviewDataForPage( *(pPage), aCurrPaintOffset, pPrevwPage );
651             pPrevwPage->bVisible = false;
652             maPrevwPages.push_back( pPrevwPage );
653         }
654 
655         // prepare data for next loop
656         pPage = static_cast<const SwPageFrm*>(pPage->GetNext());
657 
658         aCurrPaintOffset.X() += mnColWidth;
659         ++nCurrCol;
660         if ( nCurrCol > mnCols )
661         {
662             ++nConsideredRows;
663             aCurrPaintOffset.X() = aInitialPaintOffset.X();
664             nCurrCol = 1;
665             aCurrPaintOffset.Y() += mnRowHeight;
666         }
667     }
668 }
669 
670 /** determines preview data for a given page and a given preview offset
671 
672     OD 13.12.2002 #103492#
673 
674     @author OD
675 */
676 bool SwPagePreviewLayout::_CalcPreviewDataForPage( const SwPageFrm& _rPage,
677                                                    const Point& _rPrevwOffset,
678                                                    PrevwPage* _opPrevwPage )
679 {
680     // page frame
681     _opPrevwPage->pPage = &_rPage;
682     // size of page frame
683     if ( _rPage.IsEmptyPage() )
684     {
685         if ( _rPage.GetPhyPageNum() % 2 == 0 )
686              _opPrevwPage->aPageSize = _rPage.GetPrev()->Frm().SSize();
687         else
688              _opPrevwPage->aPageSize = _rPage.GetNext()->Frm().SSize();
689     }
690     else
691         _opPrevwPage->aPageSize = _rPage.Frm().SSize();
692     // position of page in preview window
693     Point aPrevwWinOffset( _rPrevwOffset );
694     if ( _opPrevwPage->aPageSize.Width() < maMaxPageSize.Width() )
695         aPrevwWinOffset.X() += ( maMaxPageSize.Width() - _opPrevwPage->aPageSize.Width() ) / 2;
696     if ( _opPrevwPage->aPageSize.Height() < maMaxPageSize.Height() )
697         aPrevwWinOffset.Y() += ( maMaxPageSize.Height() - _opPrevwPage->aPageSize.Height() ) / 2;
698     _opPrevwPage->aPrevwWinPos = aPrevwWinOffset;
699     // logic position of page and mapping offset for paint
700     if ( _rPage.IsEmptyPage() )
701     {
702         _opPrevwPage->aLogicPos = _opPrevwPage->aPrevwWinPos;
703         _opPrevwPage->aMapOffset = Point( 0, 0 );
704     }
705     else
706     {
707         _opPrevwPage->aLogicPos = _rPage.Frm().Pos();
708         _opPrevwPage->aMapOffset = _opPrevwPage->aPrevwWinPos - _opPrevwPage->aLogicPos;
709     }
710 
711     return true;
712 }
713 
714 /** enable/disable book preview
715 
716     OD 2004-03-04 #i18143#
717 
718     @author OD
719 */
720 bool SwPagePreviewLayout::SetBookPreviewMode( const bool _bEnableBookPreview,
721                                               sal_uInt16& _onStartPageNum,
722                                               Rectangle& _orDocPreviewPaintRect )
723 {
724     if ( mbBookPreview != _bEnableBookPreview)
725     {
726         mbBookPreview = _bEnableBookPreview;
727         // re-initialize page preview layout
728         ReInit();
729         // re-prepare page preview layout
730         {
731 
732             mbBookPreviewModeToggled = true;
733             Point aProposedStartPos( maPaintPreviewDocOffset );
734             // if proposed start position is below virtual preview document
735             // bottom, adjust it to the virtual preview document bottom
736             if ( aProposedStartPos.Y() > maPreviewDocRect.Bottom() )
737             {
738                 aProposedStartPos.Y() = maPreviewDocRect.Bottom();
739             }
740             Prepare( 0, aProposedStartPos,
741                         mrParentViewShell.GetOut()->LogicToPixel( maWinSize ),
742                         _onStartPageNum, _orDocPreviewPaintRect );
743             mbBookPreviewModeToggled = false;
744         }
745 
746         return true;
747     }
748 
749     return false;
750 }
751 
752 // =============================================================================
753 // methods to determine new data for changing the current shown part of the
754 // document preview.
755 // =============================================================================
756 /** calculate start position for new scale
757 
758     OD 12.12.2002 #103492#
759 
760     @author OD
761 */
762 Point SwPagePreviewLayout::GetPreviewStartPosForNewScale(
763                           const Fraction& _aNewScale,
764                           const Fraction& _aOldScale,
765                           const Size&     _aNewWinSize ) const
766 {
767     Point aNewPaintStartPos = maPaintedPrevwDocRect.TopLeft();
768     if ( _aNewScale < _aOldScale )
769     {
770         // increase paint width by moving start point to left.
771         if ( mnPrevwLayoutWidth < _aNewWinSize.Width() )
772             aNewPaintStartPos.X() = 0;
773         else if ( maPaintedPrevwDocRect.GetWidth() < _aNewWinSize.Width() )
774         {
775             aNewPaintStartPos.X() -=
776                 (_aNewWinSize.Width() - maPaintedPrevwDocRect.GetWidth()) / 2;
777             if ( aNewPaintStartPos.X() < 0)
778                 aNewPaintStartPos.X() = 0;
779         }
780 
781         if ( !mbDoesLayoutRowsFitIntoWindow )
782         {
783             // increase paint height by moving start point to top.
784             if ( mnPrevwLayoutHeight < _aNewWinSize.Height() )
785             {
786                 aNewPaintStartPos.Y() =
787                     ( (mnPaintStartRow - 1) * mnRowHeight );
788             }
789             else if ( maPaintedPrevwDocRect.GetHeight() < _aNewWinSize.Height() )
790             {
791                 aNewPaintStartPos.Y() -=
792                     (_aNewWinSize.Height() - maPaintedPrevwDocRect.GetHeight()) / 2;
793                 if ( aNewPaintStartPos.Y() < 0)
794                     aNewPaintStartPos.Y() = 0;
795             }
796         }
797     }
798     else
799     {
800         // decrease paint width by moving start point to right
801         if ( maPaintedPrevwDocRect.GetWidth() > _aNewWinSize.Width() )
802             aNewPaintStartPos.X() +=
803                 (maPaintedPrevwDocRect.GetWidth() - _aNewWinSize.Width()) / 2;
804         // decrease paint height by moving start point to bottom
805         if ( maPaintedPrevwDocRect.GetHeight() > _aNewWinSize.Height() )
806         {
807             aNewPaintStartPos.Y() +=
808                 (maPaintedPrevwDocRect.GetHeight() - _aNewWinSize.Height()) / 2;
809             // check, if new y-position is outside document preview
810             if ( aNewPaintStartPos.Y() > maPreviewDocRect.Bottom() )
811                 aNewPaintStartPos.Y() =
812                         Max( 0L, maPreviewDocRect.Bottom() - mnPrevwLayoutHeight );
813         }
814     }
815 
816     return aNewPaintStartPos;
817 }
818 
819 /** determines, if page with given page number is visible in preview
820 
821     OD 12.12.2002 #103492#
822 
823     @author OD, _nPageNum is absolute!
824 */
825 bool SwPagePreviewLayout::IsPageVisible( const sal_uInt16 _nPageNum ) const
826 {
827     const PrevwPage* pPrevwPage = _GetPrevwPageByPageNum( _nPageNum );
828     return pPrevwPage && pPrevwPage->bVisible;
829 }
830 
831 /** calculate data to bring new selected page into view.
832 
833     OD 12.12.2002 #103492#
834 
835     @author OD, IN/OUT parameters are absolute page numbers!
836 */
837 bool SwPagePreviewLayout::CalcStartValuesForSelectedPageMove(
838                                 const sal_Int16  _nHoriMove,
839                                 const sal_Int16  _nVertMove,
840                                 sal_uInt16&      _orNewSelectedPage,
841                                 sal_uInt16&      _orNewStartPage,
842                                 Point&           _orNewStartPos ) const
843 {
844     // determine position of current selected page
845     sal_uInt16 nTmpRelSelPageNum = ConvertAbsoluteToRelativePageNum( mnSelectedPageNum );
846     sal_uInt16 nNewRelSelectedPageNum = nTmpRelSelPageNum;
847 
848     // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
849     // by <mbBookPreview>.
850     if ( mbBookPreview )
851     {
852         // Note: consider that left-top-corner is left blank --> +1
853         ++nTmpRelSelPageNum;
854     }
855     sal_uInt16 nTmpCol = nTmpRelSelPageNum % mnCols;
856     sal_uInt16 nCurrRow = nTmpRelSelPageNum / mnCols;
857     if ( nTmpCol > 0 )
858         ++nCurrRow;
859 
860     // determine new selected page number
861     {
862         if ( _nHoriMove != 0 )
863         {
864             if ( (nNewRelSelectedPageNum + _nHoriMove) < 1 )
865                 nNewRelSelectedPageNum = 1;
866             else if ( (nNewRelSelectedPageNum + _nHoriMove) > mnPages )
867                 nNewRelSelectedPageNum = mnPages;
868             else
869                 nNewRelSelectedPageNum = nNewRelSelectedPageNum + _nHoriMove;
870         }
871         if ( _nVertMove != 0 )
872         {
873             if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) < 1 )
874                 nNewRelSelectedPageNum = 1;
875             else if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) > mnPages )
876                 nNewRelSelectedPageNum = mnPages;
877             else
878                 nNewRelSelectedPageNum += ( _nVertMove * mnCols );
879         }
880     }
881 
882     sal_uInt16 nNewStartPage = mnPaintPhyStartPageNum;
883     Point aNewStartPos = Point(0,0);
884 
885     sal_uInt16 nNewAbsSelectedPageNum = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
886     if ( !IsPageVisible( nNewAbsSelectedPageNum ) )
887     {
888         if ( _nHoriMove != 0 && _nVertMove != 0 )
889         {
890             ASSERT( false, "missing implementation for moving preview selected page horizontal AND vertical");
891             return false;
892         }
893 
894         // new selected page has to be brought into view considering current
895         // visible preview.
896         sal_Int16 nTotalRows = GetRowOfPage( mnPages );
897         if ( (_nHoriMove > 0 || _nVertMove > 0) &&
898             mbDoesLayoutRowsFitIntoWindow &&
899             mbDoesLayoutColsFitIntoWindow && // OD 20.02.2003 #107369# - add condition
900             nCurrRow > nTotalRows - mnRows )
901         {
902             // new proposed start page = left-top-corner of last possible
903             // preview page.
904             nNewStartPage = (nTotalRows - mnRows) * mnCols + 1;
905             // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
906             // by <mbBookPreview>.
907             if ( mbBookPreview )
908             {
909                 // Note: decrease new proposed start page number by one,
910                 // because of blank left-top-corner
911                 --nNewStartPage;
912             }
913             nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewStartPage );
914         }
915         else
916         {
917             // new proposed start page = new selected page.
918             nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
919         }
920     }
921 
922     _orNewSelectedPage = nNewAbsSelectedPageNum;
923     _orNewStartPage = nNewStartPage;
924     _orNewStartPos = aNewStartPos;
925 
926     return true;
927 }
928 
929 /** checks, if given position is inside a shown document page
930 
931     OD 17.12.2002 #103492#
932 
933     @author OD
934 */
935 struct PrevwPosInsidePagePred
936 {
937     const Point mnPrevwPos;
938     PrevwPosInsidePagePred( const Point _nPrevwPos ) : mnPrevwPos( _nPrevwPos ) {};
939     bool operator() ( const PrevwPage* _pPrevwPage )
940     {
941         if ( _pPrevwPage->bVisible )
942         {
943             Rectangle aPrevwPageRect( _pPrevwPage->aPrevwWinPos, _pPrevwPage->aPageSize );
944             return aPrevwPageRect.IsInside( mnPrevwPos ) ? true : false;
945         }
946         else
947             return false;
948     }
949 };
950 
951 bool SwPagePreviewLayout::IsPrevwPosInDocPrevwPage( const Point  _aPrevwPos,
952                                                     Point&       _orDocPos,
953                                                     bool&        _obPosInEmptyPage,
954                                                     sal_uInt16&  _onPageNum ) const
955 {
956     bool bIsPosInsideDoc;
957 
958     // initialize variable parameter values.
959     _orDocPos.X() = 0;
960     _orDocPos.Y() = 0;
961     _obPosInEmptyPage = false;
962     _onPageNum = 0;
963 
964     std::vector<PrevwPage*>::const_iterator aFoundPrevwPageIter =
965             std::find_if( maPrevwPages.begin(), maPrevwPages.end(),
966                           PrevwPosInsidePagePred( _aPrevwPos ) );
967 
968     if ( aFoundPrevwPageIter == maPrevwPages.end() )
969         // given preview position outside a document page.
970         bIsPosInsideDoc = false;
971     else
972     {
973         _onPageNum = (*aFoundPrevwPageIter)->pPage->GetPhyPageNum();
974         if ( (*aFoundPrevwPageIter)->pPage->IsEmptyPage() )
975         {
976             // given preview position inside an empty page
977             bIsPosInsideDoc = false;
978             _obPosInEmptyPage = true;
979         }
980         else
981         {
982             // given preview position inside a normal page
983             bIsPosInsideDoc = true;
984             _orDocPos = _aPrevwPos -
985                         (*aFoundPrevwPageIter)->aPrevwWinPos +
986                         (*aFoundPrevwPageIter)->aLogicPos;
987         }
988     }
989 
990     return bIsPosInsideDoc;
991 }
992 
993 /** determine window page scroll amount
994 
995     OD 17.12.2002 #103492#
996 
997     @author OD
998 */
999 SwTwips SwPagePreviewLayout::GetWinPagesScrollAmount(
1000                                 const sal_Int16 _nWinPagesToScroll ) const
1001 {
1002     SwTwips nScrollAmount;
1003     if ( mbDoesLayoutRowsFitIntoWindow )
1004     {
1005         nScrollAmount = (mnPrevwLayoutHeight - mnYFree) * _nWinPagesToScroll;
1006     }
1007     else
1008         nScrollAmount = _nWinPagesToScroll * maPaintedPrevwDocRect.GetHeight();
1009 
1010     // OD 19.02.2003 #107369# - check, if preview layout size values are valid.
1011     // If not, the checks for an adjustment of the scroll amount aren't useful.
1012     if ( mbLayoutSizesValid )
1013     {
1014         if ( (maPaintedPrevwDocRect.Top() + nScrollAmount) <= 0 )
1015             nScrollAmount = -maPaintedPrevwDocRect.Top();
1016 
1017         // OD 14.02.2003 #107369# - correct scroll amount
1018         if ( nScrollAmount > 0 &&
1019             maPaintedPrevwDocRect.Bottom() == maPreviewDocRect.Bottom()
1020             )
1021         {
1022             nScrollAmount = 0;
1023         }
1024         else
1025         {
1026             while ( (maPaintedPrevwDocRect.Top() + nScrollAmount + mnYFree) >= maPreviewDocRect.GetHeight() )
1027             {
1028                 nScrollAmount -= mnRowHeight;
1029             }
1030         }
1031     }
1032 
1033     return nScrollAmount;
1034 }
1035 
1036 // =============================================================================
1037 // methods to paint page preview layout
1038 // =============================================================================
1039 /** paint prepared preview
1040 
1041     OD 12.12.2002 #103492#
1042 
1043     @author OD
1044 */
1045 bool SwPagePreviewLayout::Paint( const Rectangle _aOutRect ) const
1046 {
1047     // check environment and parameters
1048     {
1049         if ( !mrParentViewShell.GetWin() &&
1050              !mrParentViewShell.GetOut()->GetConnectMetaFile() )
1051             return false;
1052 
1053         ASSERT( mbPaintInfoValid,
1054                 "invalid preview settings - no paint of preview" );
1055         if ( !mbPaintInfoValid )
1056             return false;
1057     }
1058 
1059     // OD 17.11.2003 #i22014# - no paint, if <superfluous> flag is set at layout
1060     if ( mrLayoutRootFrm.IsSuperfluous() )
1061     {
1062         return true;
1063     }
1064 
1065     // environment and parameter ok
1066 
1067     // OD 07.11.2003 #i22014#
1068     if ( mbInPaint )
1069     {
1070         return false;
1071     }
1072     mbInPaint = true;
1073 
1074     OutputDevice* pOutputDev = mrParentViewShell.GetOut();
1075 
1076     // prepare paint
1077     if ( maPrevwPages.size() > 0 )
1078     {
1079         mrParentViewShell.Imp()->bFirstPageInvalid = sal_False;
1080         mrParentViewShell.Imp()->pFirstVisPage =
1081                 const_cast<SwPageFrm*>(maPrevwPages[0]->pPage);
1082     }
1083 
1084     // paint preview background
1085     {
1086         SwRegionRects aPreviewBackgrdRegion( _aOutRect );
1087         // calculate preview background rectangles
1088         for ( std::vector<PrevwPage*>::const_iterator aPageIter = maPrevwPages.begin();
1089                 aPageIter != maPrevwPages.end();
1090                 ++aPageIter )
1091         {
1092             if ( (*aPageIter)->bVisible )
1093             {
1094                 aPreviewBackgrdRegion -=
1095                         SwRect( (*aPageIter)->aPrevwWinPos, (*aPageIter)->aPageSize );
1096             }
1097         }
1098         // paint preview background rectangles
1099         mrParentViewShell._PaintDesktop( aPreviewBackgrdRegion );
1100     }
1101 
1102     // prepare data for paint of pages
1103     const Rectangle aPxOutRect( pOutputDev->LogicToPixel( _aOutRect ) );
1104 
1105     MapMode aMapMode( pOutputDev->GetMapMode() );
1106     MapMode aSavedMapMode = aMapMode;
1107 
1108     const Font& rEmptyPgFont = SwPageFrm::GetEmptyPageFont();
1109 
1110     for ( std::vector<PrevwPage*>::const_iterator aPageIter = maPrevwPages.begin();
1111           aPageIter != maPrevwPages.end();
1112           ++aPageIter )
1113     {
1114         if ( !(*aPageIter)->bVisible )
1115             continue;
1116 
1117         Rectangle aPageRect( (*aPageIter)->aLogicPos, (*aPageIter)->aPageSize );
1118         aMapMode.SetOrigin( (*aPageIter)->aMapOffset );
1119         pOutputDev->SetMapMode( aMapMode );
1120         Rectangle aPxPaintRect = pOutputDev->LogicToPixel( aPageRect );
1121         if ( aPxOutRect.IsOver( aPxPaintRect) )
1122         {
1123             if ( (*aPageIter)->pPage->IsEmptyPage() )
1124             {
1125                 const Color aRetouche( mrParentViewShell.Imp()->GetRetoucheColor() );
1126                 if( pOutputDev->GetFillColor() != aRetouche )
1127                     pOutputDev->SetFillColor( aRetouche );
1128                 pOutputDev->SetLineColor(); // OD 20.02.2003 #107369# - no line color
1129                 // OD 20.02.2003 #107369# - use aligned page rectangle
1130                 {
1131                     SwRect aTmpPageRect( aPageRect );
1132                     ::SwAlignRect( aTmpPageRect, &mrParentViewShell);
1133                     aPageRect = aTmpPageRect.SVRect();
1134                 }
1135                 pOutputDev->DrawRect( aPageRect );
1136 
1137                 // paint empty page text
1138                 Font aOldFont( pOutputDev->GetFont() );
1139                 pOutputDev->SetFont( rEmptyPgFont );
1140                 pOutputDev->DrawText( aPageRect, SW_RESSTR( STR_EMPTYPAGE ),
1141                                     TEXT_DRAW_VCENTER |
1142                                     TEXT_DRAW_CENTER |
1143                                     TEXT_DRAW_CLIP );
1144                 pOutputDev->SetFont( aOldFont );
1145                 // paint border for empty page (shadow removed now)
1146                 // OD 19.02.2003 #107369# - use new method to paint page border
1147                 SwPageFrm::PaintPageBorder( aPageRect, &mrParentViewShell, true );
1148             }
1149             else
1150             {
1151                 mrParentViewShell.aVisArea = aPageRect;
1152                 aPxPaintRect.Intersection( aPxOutRect );
1153                 Rectangle aPaintRect = pOutputDev->PixelToLogic( aPxPaintRect );
1154                 mrParentViewShell.Paint( aPaintRect );
1155                 // --> OD 2007-08-15 #i80691#
1156                 // paint page border (shadow removed now)
1157                 {
1158                     SwRect aPageBorderRect;
1159                     SwPageFrm::GetBorderAndShadowBoundRect( SwRect( aPageRect ), &mrParentViewShell, aPageBorderRect, true );
1160                     const Region aDLRegion(aPageBorderRect.SVRect());
1161                     mrParentViewShell.DLPrePaint2(aDLRegion);
1162                     SwPageFrm::PaintPageBorder( aPageRect, &mrParentViewShell, true );
1163                     mrParentViewShell.DLPostPaint2(true);
1164                 }
1165                 // <--
1166             }
1167             // OD 07.11.2003 #i22014# - stop painting, because new print
1168             // preview layout is created during paint.
1169             if ( mbNewLayoutDuringPaint )
1170             {
1171                 break;
1172             }
1173 
1174             if ( (*aPageIter)->pPage->GetPhyPageNum() == mnSelectedPageNum )
1175             {
1176                 _PaintSelectMarkAtPage( (*aPageIter) );
1177             }
1178 
1179         }
1180     }
1181 
1182     // OD 17.11.2003 #i22014# - no update of accessible preview, if a new
1183     // print preview layout is created during paint.
1184     if ( !mbNewLayoutDuringPaint )
1185     {
1186         // update at accessibility interface
1187         mrParentViewShell.Imp()->UpdateAccessiblePreview(
1188                         maPrevwPages,
1189                         aMapMode.GetScaleX(),
1190                         mrLayoutRootFrm.GetPageByPageNum( mnSelectedPageNum ),
1191                         maWinSize );
1192     }
1193 
1194     pOutputDev->SetMapMode( aSavedMapMode );
1195     mrParentViewShell.aVisArea.Clear();
1196 
1197     // OD 07.11.2003 #i22014#
1198     mbInPaint = false;
1199     mbNewLayoutDuringPaint = false;
1200 
1201     return true;
1202 }
1203 
1204 /** repaint pages on page preview
1205 
1206     OD 18.12.2002 #103492#
1207 
1208     @author OD
1209 */
1210 void SwPagePreviewLayout::Repaint( const Rectangle _aInvalidCoreRect ) const
1211 {
1212     // check environment and parameters
1213     {
1214         if ( !mrParentViewShell.GetWin() &&
1215              !mrParentViewShell.GetOut()->GetConnectMetaFile() )
1216             return;
1217 
1218         ASSERT( mbPaintInfoValid,
1219                 "invalid preview settings - no paint of preview" );
1220         if ( !mbPaintInfoValid )
1221             return;
1222     }
1223 
1224     // environment and parameter OK
1225 
1226     // prepare paint
1227     if ( maPrevwPages.size() > 0 )
1228     {
1229         mrParentViewShell.Imp()->bFirstPageInvalid = sal_False;
1230         mrParentViewShell.Imp()->pFirstVisPage =
1231                 const_cast<SwPageFrm*>(maPrevwPages[0]->pPage);
1232     }
1233 
1234     // invalidate visible pages, which overlap the invalid core rectangle
1235     for ( std::vector<PrevwPage*>::const_iterator aPageIter = maPrevwPages.begin();
1236         aPageIter != maPrevwPages.end();
1237         ++aPageIter )
1238     {
1239         if ( !(*aPageIter)->bVisible )
1240             continue;
1241 
1242         Rectangle aPageRect( (*aPageIter)->aLogicPos, (*aPageIter)->aPageSize );
1243         if ( _aInvalidCoreRect.IsOver( aPageRect ) )
1244         {
1245             aPageRect.Intersection( _aInvalidCoreRect );
1246             Rectangle aInvalidPrevwRect = aPageRect;
1247             aInvalidPrevwRect.SetPos( aInvalidPrevwRect.TopLeft() -
1248                                       (*aPageIter)->aLogicPos +
1249                                       (*aPageIter)->aPrevwWinPos );
1250             mrParentViewShell.GetWin()->Invalidate( aInvalidPrevwRect );
1251         }
1252     }
1253 }
1254 
1255 /** paint selection mark at page
1256 
1257     OD 17.12.2002 #103492#
1258 
1259     @author OD
1260 */
1261 void SwPagePreviewLayout::_PaintSelectMarkAtPage(
1262                                     const PrevwPage* _aSelectedPrevwPage ) const
1263 {
1264     OutputDevice* pOutputDev = mrParentViewShell.GetOut();
1265     MapMode aMapMode( pOutputDev->GetMapMode() );
1266     // save mapping mode of output device
1267     MapMode aSavedMapMode = aMapMode;
1268     // save fill and line color of output device
1269     Color aFill( pOutputDev->GetFillColor() );
1270     Color aLine( pOutputDev->GetLineColor() );
1271 
1272     // determine selection mark color
1273     const StyleSettings& rSettings = mrParentViewShell.GetWin()->GetSettings().GetStyleSettings();
1274     Color aSelPgLineColor( rSettings.GetHighlightColor() );
1275     if ( rSettings.GetHighContrastMode() )
1276         aSelPgLineColor = rSettings.GetActiveBorderColor();
1277 
1278     // set needed mapping mode at output device
1279     aMapMode.SetOrigin( _aSelectedPrevwPage->aMapOffset );
1280     pOutputDev->SetMapMode( aMapMode );
1281 
1282     // calculate page rectangle in pixel coordinates
1283     SwRect aPageRect( _aSelectedPrevwPage->aLogicPos,
1284                       _aSelectedPrevwPage->aPageSize );
1285     // OD 19.02.2003 #107369# - use aligned page rectangle, as it is used for
1286     // page border paint - see <SwPageFrm::PaintPageBorder(..)>
1287     ::SwAlignRect( aPageRect, &mrParentViewShell);
1288     Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1289 
1290     // draw two rectangles
1291     // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1292     Rectangle aRect( aPxPageRect.Left(), aPxPageRect.Top(),
1293                      aPxPageRect.Right(), aPxPageRect.Bottom() );
1294     aRect = pOutputDev->PixelToLogic( aRect );
1295     pOutputDev->SetFillColor(); // OD 20.02.2003 #107369# - no fill color
1296     pOutputDev->SetLineColor( aSelPgLineColor );
1297     pOutputDev->DrawRect( aRect );
1298     // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1299     aRect = Rectangle( aPxPageRect.Left()+1, aPxPageRect.Top()+1,
1300                        aPxPageRect.Right()-1, aPxPageRect.Bottom()-1 );
1301     aRect = pOutputDev->PixelToLogic( aRect );
1302     pOutputDev->DrawRect( aRect );
1303 
1304     // reset fill and line color of output device
1305     pOutputDev->SetFillColor( aFill );
1306     pOutputDev->SetLineColor( aLine );
1307 
1308     // reset mapping mode of output device
1309     pOutputDev->SetMapMode( aSavedMapMode );
1310 }
1311 
1312 /** paint to mark new selected page
1313 
1314     OD 17.12.2002 #103492#
1315     Perform paint for current selected page in order to unmark it.
1316     Set new selected page and perform paint to mark this page.
1317 
1318     @author OD, _nSelectedPage, mnSelectedPage are absolute
1319 */
1320 void SwPagePreviewLayout::MarkNewSelectedPage( const sal_uInt16 _nSelectedPage )
1321 {
1322     sal_uInt16 nOldSelectedPageNum = mnSelectedPageNum;
1323     mnSelectedPageNum = _nSelectedPage;
1324 
1325     // re-paint for current selected page in order to unmark it.
1326     const PrevwPage* pOldSelectedPrevwPage = _GetPrevwPageByPageNum( nOldSelectedPageNum );
1327     if ( pOldSelectedPrevwPage && pOldSelectedPrevwPage->bVisible )
1328     {
1329         // OD 20.02.2003 #107369# - invalidate only areas of selection mark.
1330         SwRect aPageRect( pOldSelectedPrevwPage->aPrevwWinPos,
1331                           pOldSelectedPrevwPage->aPageSize );
1332         ::SwAlignRect( aPageRect, &mrParentViewShell);
1333         OutputDevice* pOutputDev = mrParentViewShell.GetOut();
1334         Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1335         // invalidate top mark line
1336         Rectangle aInvalPxRect( aPxPageRect.Left(), aPxPageRect.Top(),
1337                                 aPxPageRect.Right(), aPxPageRect.Top()+1 );
1338         mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1339         // invalidate right mark line
1340         aInvalPxRect = Rectangle( aPxPageRect.Right()-1, aPxPageRect.Top(),
1341                                   aPxPageRect.Right(), aPxPageRect.Bottom() );
1342         mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1343         // invalidate bottom mark line
1344         aInvalPxRect = Rectangle( aPxPageRect.Left(), aPxPageRect.Bottom()-1,
1345                                   aPxPageRect.Right(), aPxPageRect.Bottom() );
1346         mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1347         // invalidate left mark line
1348         aInvalPxRect = Rectangle( aPxPageRect.Left(), aPxPageRect.Top(),
1349                                   aPxPageRect.Left()+1, aPxPageRect.Bottom() );
1350         mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1351     }
1352 
1353     // re-paint for new selected page in order to mark it.
1354     const PrevwPage* pNewSelectedPrevwPage = _GetPrevwPageByPageNum( _nSelectedPage );
1355     if ( pNewSelectedPrevwPage && pNewSelectedPrevwPage->bVisible )
1356         _PaintSelectMarkAtPage( pNewSelectedPrevwPage );
1357 }
1358 
1359 
1360 // =============================================================================
1361 // helper methods
1362 // =============================================================================
1363 /** get preview page by physical page number
1364 
1365     OD 17.12.2002 #103492#
1366 
1367     @author OD
1368 */
1369 struct EqualsPageNumPred
1370 {
1371     const sal_uInt16 mnPageNum;
1372     EqualsPageNumPred( const sal_uInt16 _nPageNum ) : mnPageNum( _nPageNum ) {};
1373     bool operator() ( const PrevwPage* _pPrevwPage )
1374     {
1375         return _pPrevwPage->pPage->GetPhyPageNum() == mnPageNum;
1376     }
1377 };
1378 
1379 const PrevwPage* SwPagePreviewLayout::_GetPrevwPageByPageNum( const sal_uInt16 _nPageNum ) const
1380 {
1381     std::vector<PrevwPage*>::const_iterator aFoundPrevwPageIter =
1382             std::find_if( maPrevwPages.begin(), maPrevwPages.end(),
1383                           EqualsPageNumPred( _nPageNum ) );
1384 
1385     if ( aFoundPrevwPageIter == maPrevwPages.end() )
1386         return 0;
1387     else
1388         return (*aFoundPrevwPageIter);
1389 }
1390 
1391 /** determine row the page with the given number is in
1392 
1393     OD 17.01.2003 #103492#
1394 
1395     @author OD, _nPageNum is relative
1396 */
1397 sal_uInt16 SwPagePreviewLayout::GetRowOfPage( sal_uInt16 _nPageNum ) const
1398 {
1399     // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1400     // by <mbBookPreview>.
1401     if ( mbBookPreview )
1402     {
1403         // Note: increase given physical page number by one, because left-top-corner
1404         //       in the preview layout is left blank.
1405         ++_nPageNum;
1406     }
1407 
1408     sal_uInt16 nRow = (_nPageNum) / mnCols;
1409     if ( ( (_nPageNum) % mnCols ) > 0 )
1410         ++nRow;
1411 
1412     return nRow;
1413 }
1414 
1415 /** determine column the page with the given number is in
1416 
1417     OD 17.01.2003 #103492#
1418 
1419     @author OD, _nPageNum is relative
1420 */
1421 sal_uInt16 SwPagePreviewLayout::GetColOfPage( sal_uInt16 _nPageNum ) const
1422 {
1423     // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1424     // by <mbBookPreview>.
1425     if ( mbBookPreview )
1426     {
1427         // Note: increase given physical page number by one, because left-top-corner
1428         //       in the preview layout is left blank.
1429         ++_nPageNum;
1430     }
1431 
1432     sal_uInt16 nCol = (_nPageNum) % mnCols;
1433     if ( nCol == 0 )
1434         nCol = mnCols;
1435 
1436     return nCol;
1437 }
1438 
1439 Size SwPagePreviewLayout::GetPrevwDocSize() const
1440 {
1441     ASSERT( PreviewLayoutValid(), "PagePreviewLayout not valid" );
1442     return maPreviewDocRect.GetSize();
1443 }
1444 
1445 /** get size of a preview page by its physical page number
1446 
1447     OD 15.01.2003 #103492#
1448 
1449     @author OD
1450 */
1451 Size SwPagePreviewLayout::GetPrevwPageSizeByPageNum( sal_uInt16 _nPageNum ) const
1452 {
1453     const PrevwPage* pPrevwPage = _GetPrevwPageByPageNum( _nPageNum );
1454     if ( pPrevwPage )
1455     {
1456         return pPrevwPage->aPageSize;
1457     }
1458     else
1459     {
1460         return Size( 0, 0 );
1461     }
1462 }
1463 
1464 /** get virtual page number by its physical page number
1465 
1466     OD 21.03.2003 #108282#
1467 
1468     @author OD
1469 */
1470 sal_uInt16 SwPagePreviewLayout::GetVirtPageNumByPageNum( sal_uInt16 _nPageNum ) const
1471 {
1472     const PrevwPage* pPrevwPage = _GetPrevwPageByPageNum( _nPageNum );
1473     if ( pPrevwPage )
1474     {
1475         return pPrevwPage->pPage->GetVirtPageNum();
1476     }
1477     else
1478     {
1479         return 0;
1480     }
1481 }
1482 
1483 /** Convert absolute to relative page numbers (see PrintEmptyPages)
1484 
1485     @author FME
1486 */
1487 sal_uInt16 SwPagePreviewLayout::ConvertAbsoluteToRelativePageNum( sal_uInt16 _nAbsPageNum ) const
1488 {
1489     if ( mbBookPreview || mbPrintEmptyPages || !_nAbsPageNum )
1490     {
1491         return _nAbsPageNum;
1492     }
1493 
1494     const SwPageFrm* pTmpPage = static_cast<const SwPageFrm*>(mrLayoutRootFrm.Lower());
1495 
1496     sal_uInt16 nRet = 1;
1497 
1498     while ( pTmpPage && pTmpPage->GetPhyPageNum() != _nAbsPageNum )
1499     {
1500         if ( !pTmpPage->IsEmptyPage() )
1501             ++nRet;
1502 
1503         pTmpPage = static_cast<const SwPageFrm*>( pTmpPage->GetNext() );
1504     }
1505 
1506     return nRet;
1507 }
1508 
1509 /** Convert relative to absolute page numbers (see PrintEmptyPages)
1510 
1511     @author FME
1512 */
1513 sal_uInt16 SwPagePreviewLayout::ConvertRelativeToAbsolutePageNum( sal_uInt16 _nRelPageNum ) const
1514 {
1515     if ( mbBookPreview || mbPrintEmptyPages || !_nRelPageNum )
1516     {
1517         return _nRelPageNum;
1518     }
1519 
1520     const SwPageFrm* pTmpPage = static_cast<const SwPageFrm*>(mrLayoutRootFrm.Lower());
1521     const SwPageFrm* pRet = 0;
1522 
1523     sal_uInt16 i = 0;
1524     while( pTmpPage && i != _nRelPageNum )
1525     {
1526         if ( !pTmpPage->IsEmptyPage() )
1527             ++i;
1528 
1529         pRet = pTmpPage;
1530         pTmpPage = static_cast<const SwPageFrm*>( pTmpPage->GetNext() );
1531     }
1532 
1533     return pRet->GetPhyPageNum();
1534 }
1535 
1536 /* vim: set noet sw=4 ts=4: */
1537