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