xref: /trunk/main/sw/source/core/view/pagepreviewlayout.cxx (revision 31bbceb0f9d64c0c2c3b22a794a1666c1f33396e)
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     bool bRet = false;
725     if ( mbBookPreview != _bEnableBookPreview)
726     {
727         mbBookPreview = _bEnableBookPreview;
728         // re-initialize page preview layout
729         ReInit();
730         // re-prepare page preview layout
731         {
732 
733             mbBookPreviewModeToggled = true;
734             Point aProposedStartPos( maPaintPreviewDocOffset );
735             // if proposed start position is below virtual preview document
736             // bottom, adjust it to the virtual preview document bottom
737             if ( aProposedStartPos.Y() > maPreviewDocRect.Bottom() )
738             {
739                 aProposedStartPos.Y() = maPreviewDocRect.Bottom();
740             }
741             Prepare( 0, aProposedStartPos,
742                         mrParentViewShell.GetOut()->LogicToPixel( maWinSize ),
743                         _onStartPageNum, _orDocPreviewPaintRect );
744             mbBookPreviewModeToggled = false;
745         }
746 
747         bRet = true;
748     }
749 
750     return bRet;
751 }
752 
753 // =============================================================================
754 // methods to determine new data for changing the current shown part of the
755 // document preview.
756 // =============================================================================
757 /** calculate start position for new scale
758 
759     OD 12.12.2002 #103492#
760 
761     @author OD
762 */
763 Point SwPagePreviewLayout::GetPreviewStartPosForNewScale(
764                           const Fraction& _aNewScale,
765                           const Fraction& _aOldScale,
766                           const Size&     _aNewWinSize ) const
767 {
768     Point aNewPaintStartPos = maPaintedPrevwDocRect.TopLeft();
769     if ( _aNewScale < _aOldScale )
770     {
771         // increase paint width by moving start point to left.
772         if ( mnPrevwLayoutWidth < _aNewWinSize.Width() )
773             aNewPaintStartPos.X() = 0;
774         else if ( maPaintedPrevwDocRect.GetWidth() < _aNewWinSize.Width() )
775         {
776             aNewPaintStartPos.X() -=
777                 (_aNewWinSize.Width() - maPaintedPrevwDocRect.GetWidth()) / 2;
778             if ( aNewPaintStartPos.X() < 0)
779                 aNewPaintStartPos.X() = 0;
780         }
781 
782         if ( !mbDoesLayoutRowsFitIntoWindow )
783         {
784             // increase paint height by moving start point to top.
785             if ( mnPrevwLayoutHeight < _aNewWinSize.Height() )
786             {
787                 aNewPaintStartPos.Y() =
788                     ( (mnPaintStartRow - 1) * mnRowHeight );
789             }
790             else if ( maPaintedPrevwDocRect.GetHeight() < _aNewWinSize.Height() )
791             {
792                 aNewPaintStartPos.Y() -=
793                     (_aNewWinSize.Height() - maPaintedPrevwDocRect.GetHeight()) / 2;
794                 if ( aNewPaintStartPos.Y() < 0)
795                     aNewPaintStartPos.Y() = 0;
796             }
797         }
798     }
799     else
800     {
801         // decrease paint width by moving start point to right
802         if ( maPaintedPrevwDocRect.GetWidth() > _aNewWinSize.Width() )
803             aNewPaintStartPos.X() +=
804                 (maPaintedPrevwDocRect.GetWidth() - _aNewWinSize.Width()) / 2;
805         // decrease paint height by moving start point to bottom
806         if ( maPaintedPrevwDocRect.GetHeight() > _aNewWinSize.Height() )
807         {
808             aNewPaintStartPos.Y() +=
809                 (maPaintedPrevwDocRect.GetHeight() - _aNewWinSize.Height()) / 2;
810             // check, if new y-position is outside document preview
811             if ( aNewPaintStartPos.Y() > maPreviewDocRect.Bottom() )
812                 aNewPaintStartPos.Y() =
813                         Max( 0L, maPreviewDocRect.Bottom() - mnPrevwLayoutHeight );
814         }
815     }
816 
817     return aNewPaintStartPos;
818 }
819 
820 /** determines, if page with given page number is visible in preview
821 
822     OD 12.12.2002 #103492#
823 
824     @author OD, _nPageNum is absolute!
825 */
826 bool SwPagePreviewLayout::IsPageVisible( const sal_uInt16 _nPageNum ) const
827 {
828     const PrevwPage* pPrevwPage = _GetPrevwPageByPageNum( _nPageNum );
829     return pPrevwPage && pPrevwPage->bVisible;
830 }
831 
832 /** calculate data to bring new selected page into view.
833 
834     OD 12.12.2002 #103492#
835 
836     @author OD, IN/OUT parameters are absolute page numbers!
837 */
838 bool SwPagePreviewLayout::CalcStartValuesForSelectedPageMove(
839                                 const sal_Int16  _nHoriMove,
840                                 const sal_Int16  _nVertMove,
841                                 sal_uInt16&      _orNewSelectedPage,
842                                 sal_uInt16&      _orNewStartPage,
843                                 Point&           _orNewStartPos ) const
844 {
845     // determine position of current selected page
846     sal_uInt16 nTmpRelSelPageNum = ConvertAbsoluteToRelativePageNum( mnSelectedPageNum );
847     sal_uInt16 nNewRelSelectedPageNum = nTmpRelSelPageNum;
848 
849     // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
850     // by <mbBookPreview>.
851     if ( mbBookPreview )
852     {
853         // Note: consider that left-top-corner is left blank --> +1
854         ++nTmpRelSelPageNum;
855     }
856     sal_uInt16 nTmpCol = nTmpRelSelPageNum % mnCols;
857     sal_uInt16 nCurrRow = nTmpRelSelPageNum / mnCols;
858     if ( nTmpCol > 0 )
859         ++nCurrRow;
860 
861     // determine new selected page number
862     {
863         if ( _nHoriMove != 0 )
864         {
865             if ( (nNewRelSelectedPageNum + _nHoriMove) < 1 )
866                 nNewRelSelectedPageNum = 1;
867             else if ( (nNewRelSelectedPageNum + _nHoriMove) > mnPages )
868                 nNewRelSelectedPageNum = mnPages;
869             else
870                 nNewRelSelectedPageNum = nNewRelSelectedPageNum + _nHoriMove;
871         }
872         if ( _nVertMove != 0 )
873         {
874             if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) < 1 )
875                 nNewRelSelectedPageNum = 1;
876             else if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) > mnPages )
877                 nNewRelSelectedPageNum = mnPages;
878             else
879                 nNewRelSelectedPageNum += ( _nVertMove * mnCols );
880         }
881     }
882 
883     sal_uInt16 nNewStartPage = mnPaintPhyStartPageNum;
884     Point aNewStartPos = Point(0,0);
885 
886     sal_uInt16 nNewAbsSelectedPageNum = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
887     if ( !IsPageVisible( nNewAbsSelectedPageNum ) )
888     {
889         if ( _nHoriMove != 0 && _nVertMove != 0 )
890         {
891             ASSERT( false, "missing implementation for moving preview selected page horizontal AND vertical");
892             return false;
893         }
894 
895         // new selected page has to be brought into view considering current
896         // visible preview.
897         sal_Int16 nTotalRows = GetRowOfPage( mnPages );
898         if ( (_nHoriMove > 0 || _nVertMove > 0) &&
899             mbDoesLayoutRowsFitIntoWindow &&
900             mbDoesLayoutColsFitIntoWindow && // OD 20.02.2003 #107369# - add condition
901             nCurrRow > nTotalRows - mnRows )
902         {
903             // new proposed start page = left-top-corner of last possible
904             // preview page.
905             nNewStartPage = (nTotalRows - mnRows) * mnCols + 1;
906             // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
907             // by <mbBookPreview>.
908             if ( mbBookPreview )
909             {
910                 // Note: decrease new proposed start page number by one,
911                 // because of blank left-top-corner
912                 --nNewStartPage;
913             }
914             nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewStartPage );
915         }
916         else
917         {
918             // new proposed start page = new selected page.
919             nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
920         }
921     }
922 
923     _orNewSelectedPage = nNewAbsSelectedPageNum;
924     _orNewStartPage = nNewStartPage;
925     _orNewStartPos = aNewStartPos;
926 
927     return true;
928 }
929 
930 /** checks, if given position is inside a shown document page
931 
932     OD 17.12.2002 #103492#
933 
934     @author OD
935 */
936 struct PrevwPosInsidePagePred
937 {
938     const Point mnPrevwPos;
939     PrevwPosInsidePagePred( const Point _nPrevwPos ) : mnPrevwPos( _nPrevwPos ) {};
940     bool operator() ( const PrevwPage* _pPrevwPage )
941     {
942         if ( _pPrevwPage->bVisible )
943         {
944             Rectangle aPrevwPageRect( _pPrevwPage->aPrevwWinPos, _pPrevwPage->aPageSize );
945             return aPrevwPageRect.IsInside( mnPrevwPos ) ? true : false;
946         }
947         else
948             return false;
949     }
950 };
951 
952 bool SwPagePreviewLayout::IsPrevwPosInDocPrevwPage( const Point  _aPrevwPos,
953                                                     Point&       _orDocPos,
954                                                     bool&        _obPosInEmptyPage,
955                                                     sal_uInt16&  _onPageNum ) const
956 {
957     bool bIsPosInsideDoc;
958 
959     // initialize variable parameter values.
960     _orDocPos.X() = 0;
961     _orDocPos.Y() = 0;
962     _obPosInEmptyPage = false;
963     _onPageNum = 0;
964 
965     std::vector<PrevwPage*>::const_iterator aFoundPrevwPageIter =
966             std::find_if( maPrevwPages.begin(), maPrevwPages.end(),
967                           PrevwPosInsidePagePred( _aPrevwPos ) );
968 
969     if ( aFoundPrevwPageIter == maPrevwPages.end() )
970         // given preview position outside a document page.
971         bIsPosInsideDoc = false;
972     else
973     {
974         _onPageNum = (*aFoundPrevwPageIter)->pPage->GetPhyPageNum();
975         if ( (*aFoundPrevwPageIter)->pPage->IsEmptyPage() )
976         {
977             // given preview position inside an empty page
978             bIsPosInsideDoc = false;
979             _obPosInEmptyPage = true;
980         }
981         else
982         {
983             // given preview position inside a normal page
984             bIsPosInsideDoc = true;
985             _orDocPos = _aPrevwPos -
986                         (*aFoundPrevwPageIter)->aPrevwWinPos +
987                         (*aFoundPrevwPageIter)->aLogicPos;
988         }
989     }
990 
991     return bIsPosInsideDoc;
992 }
993 
994 /** determine window page scroll amount
995 
996     OD 17.12.2002 #103492#
997 
998     @author OD
999 */
1000 SwTwips SwPagePreviewLayout::GetWinPagesScrollAmount(
1001                                 const sal_Int16 _nWinPagesToScroll ) const
1002 {
1003     SwTwips nScrollAmount;
1004     if ( mbDoesLayoutRowsFitIntoWindow )
1005     {
1006         nScrollAmount = (mnPrevwLayoutHeight - mnYFree) * _nWinPagesToScroll;
1007     }
1008     else
1009         nScrollAmount = _nWinPagesToScroll * maPaintedPrevwDocRect.GetHeight();
1010 
1011     // OD 19.02.2003 #107369# - check, if preview layout size values are valid.
1012     // If not, the checks for an adjustment of the scroll amount aren't useful.
1013     if ( mbLayoutSizesValid )
1014     {
1015         if ( (maPaintedPrevwDocRect.Top() + nScrollAmount) <= 0 )
1016             nScrollAmount = -maPaintedPrevwDocRect.Top();
1017 
1018         // OD 14.02.2003 #107369# - correct scroll amount
1019         if ( nScrollAmount > 0 &&
1020             maPaintedPrevwDocRect.Bottom() == maPreviewDocRect.Bottom()
1021             )
1022         {
1023             nScrollAmount = 0;
1024         }
1025         else
1026         {
1027             while ( (maPaintedPrevwDocRect.Top() + nScrollAmount + mnYFree) >= maPreviewDocRect.GetHeight() )
1028             {
1029                 nScrollAmount -= mnRowHeight;
1030             }
1031         }
1032     }
1033 
1034     return nScrollAmount;
1035 }
1036 
1037 // =============================================================================
1038 // methods to paint page preview layout
1039 // =============================================================================
1040 /** paint prepared preview
1041 
1042     OD 12.12.2002 #103492#
1043 
1044     @author OD
1045 */
1046 bool SwPagePreviewLayout::Paint( const Rectangle _aOutRect ) const
1047 {
1048     // check environment and parameters
1049     {
1050         if ( !mrParentViewShell.GetWin() &&
1051              !mrParentViewShell.GetOut()->GetConnectMetaFile() )
1052             return false;
1053 
1054         ASSERT( mbPaintInfoValid,
1055                 "invalid preview settings - no paint of preview" );
1056         if ( !mbPaintInfoValid )
1057             return false;
1058     }
1059 
1060     // OD 17.11.2003 #i22014# - no paint, if <superfluous> flag is set at layout
1061     if ( mrLayoutRootFrm.IsSuperfluous() )
1062     {
1063         return true;
1064     }
1065 
1066     // environment and parameter ok
1067 
1068     // OD 07.11.2003 #i22014#
1069     if ( mbInPaint )
1070     {
1071         return false;
1072     }
1073     mbInPaint = true;
1074 
1075     OutputDevice* pOutputDev = mrParentViewShell.GetOut();
1076 
1077     // prepare paint
1078     if ( maPrevwPages.size() > 0 )
1079     {
1080         mrParentViewShell.Imp()->bFirstPageInvalid = sal_False;
1081         mrParentViewShell.Imp()->pFirstVisPage =
1082                 const_cast<SwPageFrm*>(maPrevwPages[0]->pPage);
1083     }
1084 
1085     // paint preview background
1086     {
1087         SwRegionRects aPreviewBackgrdRegion( _aOutRect );
1088         // calculate preview background rectangles
1089         for ( std::vector<PrevwPage*>::const_iterator aPageIter = maPrevwPages.begin();
1090                 aPageIter != maPrevwPages.end();
1091                 ++aPageIter )
1092         {
1093             if ( (*aPageIter)->bVisible )
1094             {
1095                 aPreviewBackgrdRegion -=
1096                         SwRect( (*aPageIter)->aPrevwWinPos, (*aPageIter)->aPageSize );
1097             }
1098         }
1099         // paint preview background rectangles
1100         mrParentViewShell._PaintDesktop( aPreviewBackgrdRegion );
1101     }
1102 
1103     // prepare data for paint of pages
1104     const Rectangle aPxOutRect( pOutputDev->LogicToPixel( _aOutRect ) );
1105 
1106     MapMode aMapMode( pOutputDev->GetMapMode() );
1107     MapMode aSavedMapMode = aMapMode;
1108 
1109     const Font& rEmptyPgFont = SwPageFrm::GetEmptyPageFont();
1110 
1111     for ( std::vector<PrevwPage*>::const_iterator aPageIter = maPrevwPages.begin();
1112           aPageIter != maPrevwPages.end();
1113           ++aPageIter )
1114     {
1115         if ( !(*aPageIter)->bVisible )
1116             continue;
1117 
1118         Rectangle aPageRect( (*aPageIter)->aLogicPos, (*aPageIter)->aPageSize );
1119         aMapMode.SetOrigin( (*aPageIter)->aMapOffset );
1120         pOutputDev->SetMapMode( aMapMode );
1121         Rectangle aPxPaintRect = pOutputDev->LogicToPixel( aPageRect );
1122         if ( aPxOutRect.IsOver( aPxPaintRect) )
1123         {
1124             if ( (*aPageIter)->pPage->IsEmptyPage() )
1125             {
1126                 const Color aRetouche( mrParentViewShell.Imp()->GetRetoucheColor() );
1127                 if( pOutputDev->GetFillColor() != aRetouche )
1128                     pOutputDev->SetFillColor( aRetouche );
1129                 pOutputDev->SetLineColor(); // OD 20.02.2003 #107369# - no line color
1130                 // OD 20.02.2003 #107369# - use aligned page rectangle
1131                 {
1132                     SwRect aTmpPageRect( aPageRect );
1133                     ::SwAlignRect( aTmpPageRect, &mrParentViewShell);
1134                     aPageRect = aTmpPageRect.SVRect();
1135                 }
1136                 pOutputDev->DrawRect( aPageRect );
1137 
1138                 // paint empty page text
1139                 Font aOldFont( pOutputDev->GetFont() );
1140                 pOutputDev->SetFont( rEmptyPgFont );
1141                 pOutputDev->DrawText( aPageRect, SW_RESSTR( STR_EMPTYPAGE ),
1142                                     TEXT_DRAW_VCENTER |
1143                                     TEXT_DRAW_CENTER |
1144                                     TEXT_DRAW_CLIP );
1145                 pOutputDev->SetFont( aOldFont );
1146                 // paint border for empty page (shadow removed now)
1147                 // OD 19.02.2003 #107369# - use new method to paint page border
1148                 SwPageFrm::PaintPageBorder( aPageRect, &mrParentViewShell, true );
1149             }
1150             else
1151             {
1152                 mrParentViewShell.aVisArea = aPageRect;
1153                 aPxPaintRect.Intersection( aPxOutRect );
1154                 Rectangle aPaintRect = pOutputDev->PixelToLogic( aPxPaintRect );
1155                 mrParentViewShell.Paint( aPaintRect );
1156                 // --> OD 2007-08-15 #i80691#
1157                 // paint page border (shadow removed now)
1158                 {
1159                     SwRect aPageBorderRect;
1160                     SwPageFrm::GetBorderAndShadowBoundRect( SwRect( aPageRect ), &mrParentViewShell, aPageBorderRect, true );
1161                     const Region aDLRegion(aPageBorderRect.SVRect());
1162                     mrParentViewShell.DLPrePaint2(aDLRegion);
1163                     SwPageFrm::PaintPageBorder( aPageRect, &mrParentViewShell, true );
1164                     mrParentViewShell.DLPostPaint2(true);
1165                 }
1166                 // <--
1167             }
1168             // OD 07.11.2003 #i22014# - stop painting, because new print
1169             // preview layout is created during paint.
1170             if ( mbNewLayoutDuringPaint )
1171             {
1172                 break;
1173             }
1174 
1175             if ( (*aPageIter)->pPage->GetPhyPageNum() == mnSelectedPageNum )
1176             {
1177                 _PaintSelectMarkAtPage( (*aPageIter) );
1178             }
1179 
1180         }
1181     }
1182 
1183     // OD 17.11.2003 #i22014# - no update of accessible preview, if a new
1184     // print preview layout is created during paint.
1185     if ( !mbNewLayoutDuringPaint )
1186     {
1187         // update at accessibility interface
1188         mrParentViewShell.Imp()->UpdateAccessiblePreview(
1189                         maPrevwPages,
1190                         aMapMode.GetScaleX(),
1191                         mrLayoutRootFrm.GetPageByPageNum( mnSelectedPageNum ),
1192                         maWinSize );
1193     }
1194 
1195     pOutputDev->SetMapMode( aSavedMapMode );
1196     mrParentViewShell.aVisArea.Clear();
1197 
1198     // OD 07.11.2003 #i22014#
1199     mbInPaint = false;
1200     mbNewLayoutDuringPaint = false;
1201 
1202     return true;
1203 }
1204 
1205 /** repaint pages on page preview
1206 
1207     OD 18.12.2002 #103492#
1208 
1209     @author OD
1210 */
1211 void SwPagePreviewLayout::Repaint( const Rectangle _aInvalidCoreRect ) const
1212 {
1213     // check environment and parameters
1214     {
1215         if ( !mrParentViewShell.GetWin() &&
1216              !mrParentViewShell.GetOut()->GetConnectMetaFile() )
1217             return;
1218 
1219         ASSERT( mbPaintInfoValid,
1220                 "invalid preview settings - no paint of preview" );
1221         if ( !mbPaintInfoValid )
1222             return;
1223     }
1224 
1225     // environment and parameter OK
1226 
1227     // prepare paint
1228     if ( maPrevwPages.size() > 0 )
1229     {
1230         mrParentViewShell.Imp()->bFirstPageInvalid = sal_False;
1231         mrParentViewShell.Imp()->pFirstVisPage =
1232                 const_cast<SwPageFrm*>(maPrevwPages[0]->pPage);
1233     }
1234 
1235     // invalidate visible pages, which overlap the invalid core rectangle
1236     for ( std::vector<PrevwPage*>::const_iterator aPageIter = maPrevwPages.begin();
1237         aPageIter != maPrevwPages.end();
1238         ++aPageIter )
1239     {
1240         if ( !(*aPageIter)->bVisible )
1241             continue;
1242 
1243         Rectangle aPageRect( (*aPageIter)->aLogicPos, (*aPageIter)->aPageSize );
1244         if ( _aInvalidCoreRect.IsOver( aPageRect ) )
1245         {
1246             aPageRect.Intersection( _aInvalidCoreRect );
1247             Rectangle aInvalidPrevwRect = aPageRect;
1248             aInvalidPrevwRect.SetPos( aInvalidPrevwRect.TopLeft() -
1249                                       (*aPageIter)->aLogicPos +
1250                                       (*aPageIter)->aPrevwWinPos );
1251             mrParentViewShell.GetWin()->Invalidate( aInvalidPrevwRect );
1252         }
1253     }
1254 }
1255 
1256 /** paint selection mark at page
1257 
1258     OD 17.12.2002 #103492#
1259 
1260     @author OD
1261 */
1262 void SwPagePreviewLayout::_PaintSelectMarkAtPage(
1263                                     const PrevwPage* _aSelectedPrevwPage ) const
1264 {
1265     OutputDevice* pOutputDev = mrParentViewShell.GetOut();
1266     MapMode aMapMode( pOutputDev->GetMapMode() );
1267     // save mapping mode of output device
1268     MapMode aSavedMapMode = aMapMode;
1269     // save fill and line color of output device
1270     Color aFill( pOutputDev->GetFillColor() );
1271     Color aLine( pOutputDev->GetLineColor() );
1272 
1273     // determine selection mark color
1274     const StyleSettings& rSettings = mrParentViewShell.GetWin()->GetSettings().GetStyleSettings();
1275     Color aSelPgLineColor( rSettings.GetHighlightColor() );
1276     if ( rSettings.GetHighContrastMode() )
1277         aSelPgLineColor = rSettings.GetActiveBorderColor();
1278 
1279     // set needed mapping mode at output device
1280     aMapMode.SetOrigin( _aSelectedPrevwPage->aMapOffset );
1281     pOutputDev->SetMapMode( aMapMode );
1282 
1283     // calculate page rectangle in pixel coordinates
1284     SwRect aPageRect( _aSelectedPrevwPage->aLogicPos,
1285                       _aSelectedPrevwPage->aPageSize );
1286     // OD 19.02.2003 #107369# - use aligned page rectangle, as it is used for
1287     // page border paint - see <SwPageFrm::PaintPageBorder(..)>
1288     ::SwAlignRect( aPageRect, &mrParentViewShell);
1289     Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1290 
1291     // draw two rectangles
1292     // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1293     Rectangle aRect( aPxPageRect.Left(), aPxPageRect.Top(),
1294                      aPxPageRect.Right(), aPxPageRect.Bottom() );
1295     aRect = pOutputDev->PixelToLogic( aRect );
1296     pOutputDev->SetFillColor(); // OD 20.02.2003 #107369# - no fill color
1297     pOutputDev->SetLineColor( aSelPgLineColor );
1298     pOutputDev->DrawRect( aRect );
1299     // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1300     aRect = Rectangle( aPxPageRect.Left()+1, aPxPageRect.Top()+1,
1301                        aPxPageRect.Right()-1, aPxPageRect.Bottom()-1 );
1302     aRect = pOutputDev->PixelToLogic( aRect );
1303     pOutputDev->DrawRect( aRect );
1304 
1305     // reset fill and line color of output device
1306     pOutputDev->SetFillColor( aFill );
1307     pOutputDev->SetLineColor( aLine );
1308 
1309     // reset mapping mode of output device
1310     pOutputDev->SetMapMode( aSavedMapMode );
1311 }
1312 
1313 /** paint to mark new selected page
1314 
1315     OD 17.12.2002 #103492#
1316     Perform paint for current selected page in order to unmark it.
1317     Set new selected page and perform paint to mark this page.
1318 
1319     @author OD, _nSelectedPage, mnSelectedPage are absolute
1320 */
1321 void SwPagePreviewLayout::MarkNewSelectedPage( const sal_uInt16 _nSelectedPage )
1322 {
1323     sal_uInt16 nOldSelectedPageNum = mnSelectedPageNum;
1324     mnSelectedPageNum = _nSelectedPage;
1325 
1326     // re-paint for current selected page in order to unmark it.
1327     const PrevwPage* pOldSelectedPrevwPage = _GetPrevwPageByPageNum( nOldSelectedPageNum );
1328     if ( pOldSelectedPrevwPage && pOldSelectedPrevwPage->bVisible )
1329     {
1330         // OD 20.02.2003 #107369# - invalidate only areas of selection mark.
1331         SwRect aPageRect( pOldSelectedPrevwPage->aPrevwWinPos,
1332                           pOldSelectedPrevwPage->aPageSize );
1333         ::SwAlignRect( aPageRect, &mrParentViewShell);
1334         OutputDevice* pOutputDev = mrParentViewShell.GetOut();
1335         Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1336         // invalidate top mark line
1337         Rectangle aInvalPxRect( aPxPageRect.Left(), aPxPageRect.Top(),
1338                                 aPxPageRect.Right(), aPxPageRect.Top()+1 );
1339         mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1340         // invalidate right mark line
1341         aInvalPxRect = Rectangle( aPxPageRect.Right()-1, aPxPageRect.Top(),
1342                                   aPxPageRect.Right(), aPxPageRect.Bottom() );
1343         mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1344         // invalidate bottom mark line
1345         aInvalPxRect = Rectangle( aPxPageRect.Left(), aPxPageRect.Bottom()-1,
1346                                   aPxPageRect.Right(), aPxPageRect.Bottom() );
1347         mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1348         // invalidate left mark line
1349         aInvalPxRect = Rectangle( aPxPageRect.Left(), aPxPageRect.Top(),
1350                                   aPxPageRect.Left()+1, aPxPageRect.Bottom() );
1351         mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1352     }
1353 
1354     // re-paint for new selected page in order to mark it.
1355     const PrevwPage* pNewSelectedPrevwPage = _GetPrevwPageByPageNum( _nSelectedPage );
1356     if ( pNewSelectedPrevwPage && pNewSelectedPrevwPage->bVisible )
1357         _PaintSelectMarkAtPage( pNewSelectedPrevwPage );
1358 }
1359 
1360 
1361 // =============================================================================
1362 // helper methods
1363 // =============================================================================
1364 /** get preview page by physical page number
1365 
1366     OD 17.12.2002 #103492#
1367 
1368     @author OD
1369 */
1370 struct EqualsPageNumPred
1371 {
1372     const sal_uInt16 mnPageNum;
1373     EqualsPageNumPred( const sal_uInt16 _nPageNum ) : mnPageNum( _nPageNum ) {};
1374     bool operator() ( const PrevwPage* _pPrevwPage )
1375     {
1376         return _pPrevwPage->pPage->GetPhyPageNum() == mnPageNum;
1377     }
1378 };
1379 
1380 const PrevwPage* SwPagePreviewLayout::_GetPrevwPageByPageNum( const sal_uInt16 _nPageNum ) const
1381 {
1382     std::vector<PrevwPage*>::const_iterator aFoundPrevwPageIter =
1383             std::find_if( maPrevwPages.begin(), maPrevwPages.end(),
1384                           EqualsPageNumPred( _nPageNum ) );
1385 
1386     if ( aFoundPrevwPageIter == maPrevwPages.end() )
1387         return 0;
1388     else
1389         return (*aFoundPrevwPageIter);
1390 }
1391 
1392 /** determine row the page with the given number is in
1393 
1394     OD 17.01.2003 #103492#
1395 
1396     @author OD, _nPageNum is relative
1397 */
1398 sal_uInt16 SwPagePreviewLayout::GetRowOfPage( sal_uInt16 _nPageNum ) const
1399 {
1400     // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1401     // by <mbBookPreview>.
1402     if ( mbBookPreview )
1403     {
1404         // Note: increase given physical page number by one, because left-top-corner
1405         //       in the preview layout is left blank.
1406         ++_nPageNum;
1407     }
1408 
1409     sal_uInt16 nRow = (_nPageNum) / mnCols;
1410     if ( ( (_nPageNum) % mnCols ) > 0 )
1411         ++nRow;
1412 
1413     return nRow;
1414 }
1415 
1416 /** determine column the page with the given number is in
1417 
1418     OD 17.01.2003 #103492#
1419 
1420     @author OD, _nPageNum is relative
1421 */
1422 sal_uInt16 SwPagePreviewLayout::GetColOfPage( sal_uInt16 _nPageNum ) const
1423 {
1424     // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1425     // by <mbBookPreview>.
1426     if ( mbBookPreview )
1427     {
1428         // Note: increase given physical page number by one, because left-top-corner
1429         //       in the preview layout is left blank.
1430         ++_nPageNum;
1431     }
1432 
1433     sal_uInt16 nCol = (_nPageNum) % mnCols;
1434     if ( nCol == 0 )
1435         nCol = mnCols;
1436 
1437     return nCol;
1438 }
1439 
1440 Size SwPagePreviewLayout::GetPrevwDocSize() const
1441 {
1442     ASSERT( PreviewLayoutValid(), "PagePreviewLayout not valid" );
1443     return maPreviewDocRect.GetSize();
1444 }
1445 
1446 /** get size of a preview page by its physical page number
1447 
1448     OD 15.01.2003 #103492#
1449 
1450     @author OD
1451 */
1452 Size SwPagePreviewLayout::GetPrevwPageSizeByPageNum( sal_uInt16 _nPageNum ) const
1453 {
1454     const PrevwPage* pPrevwPage = _GetPrevwPageByPageNum( _nPageNum );
1455     if ( pPrevwPage )
1456     {
1457         return pPrevwPage->aPageSize;
1458     }
1459     else
1460     {
1461         return Size( 0, 0 );
1462     }
1463 }
1464 
1465 /** get virtual page number by its physical page number
1466 
1467     OD 21.03.2003 #108282#
1468 
1469     @author OD
1470 */
1471 sal_uInt16 SwPagePreviewLayout::GetVirtPageNumByPageNum( sal_uInt16 _nPageNum ) const
1472 {
1473     const PrevwPage* pPrevwPage = _GetPrevwPageByPageNum( _nPageNum );
1474     if ( pPrevwPage )
1475     {
1476         return pPrevwPage->pPage->GetVirtPageNum();
1477     }
1478     else
1479     {
1480         return 0;
1481     }
1482 }
1483 
1484 /** Convert absolute to relative page numbers (see PrintEmptyPages)
1485 
1486     @author FME
1487 */
1488 sal_uInt16 SwPagePreviewLayout::ConvertAbsoluteToRelativePageNum( sal_uInt16 _nAbsPageNum ) const
1489 {
1490     if ( mbBookPreview || mbPrintEmptyPages || !_nAbsPageNum )
1491     {
1492         return _nAbsPageNum;
1493     }
1494 
1495     const SwPageFrm* pTmpPage = static_cast<const SwPageFrm*>(mrLayoutRootFrm.Lower());
1496 
1497     sal_uInt16 nRet = 1;
1498 
1499     while ( pTmpPage && pTmpPage->GetPhyPageNum() != _nAbsPageNum )
1500     {
1501         if ( !pTmpPage->IsEmptyPage() )
1502             ++nRet;
1503 
1504         pTmpPage = static_cast<const SwPageFrm*>( pTmpPage->GetNext() );
1505     }
1506 
1507     return nRet;
1508 }
1509 
1510 /** Convert relative to absolute page numbers (see PrintEmptyPages)
1511 
1512     @author FME
1513 */
1514 sal_uInt16 SwPagePreviewLayout::ConvertRelativeToAbsolutePageNum( sal_uInt16 _nRelPageNum ) const
1515 {
1516     if ( mbBookPreview || mbPrintEmptyPages || !_nRelPageNum )
1517     {
1518         return _nRelPageNum;
1519     }
1520 
1521     const SwPageFrm* pTmpPage = static_cast<const SwPageFrm*>(mrLayoutRootFrm.Lower());
1522     const SwPageFrm* pRet = 0;
1523 
1524     sal_uInt16 i = 0;
1525     while( pTmpPage && i != _nRelPageNum )
1526     {
1527         if ( !pTmpPage->IsEmptyPage() )
1528             ++i;
1529 
1530         pRet = pTmpPage;
1531         pTmpPage = static_cast<const SwPageFrm*>( pTmpPage->GetNext() );
1532     }
1533 
1534     return pRet->GetPhyPageNum();
1535 }
1536 
1537 /* vim: set noet sw=4 ts=4: */
1538