LCOV - code coverage report
Current view: top level - sd/source/ui/slidesorter/view - SlsLayouter.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 206 422 48.8 %
Date: 2015-06-13 12:38:46 Functions: 43 67 64.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "view/SlsLayouter.hxx"
      21             : #include "model/SlideSorterModel.hxx"
      22             : #include "model/SlsPageDescriptor.hxx"
      23             : #include "Window.hxx"
      24             : #include <rtl/math.hxx>
      25             : #include <basegfx/numeric/ftools.hxx>
      26             : 
      27             : namespace sd { namespace slidesorter { namespace view {
      28             : 
      29             : class Layouter::Implementation
      30             : {
      31             : public:
      32             :     VclPtr<sd::Window> mpWindow;
      33             :     sal_Int32 mnRequestedLeftBorder;
      34             :     sal_Int32 mnRequestedRightBorder;
      35             :     sal_Int32 mnRequestedTopBorder;
      36             :     sal_Int32 mnRequestedBottomBorder;
      37             :     sal_Int32 mnLeftBorder;
      38             :     sal_Int32 mnRightBorder;
      39             :     sal_Int32 mnTopBorder;
      40             :     sal_Int32 mnBottomBorder;
      41             :     sal_Int32 mnVerticalGap;
      42             :     sal_Int32 mnHorizontalGap;
      43             :     Size maMinimalSize;
      44             :     Size maPreferredSize;
      45             :     Size maMaximalSize;
      46             :     sal_Int32 mnMinimalColumnCount;
      47             :     sal_Int32 mnMaximalColumnCount;
      48             :     sal_Int32 mnPageCount;
      49             :     sal_Int32 mnColumnCount;
      50             :     sal_Int32 mnRowCount;
      51             :     /// The maximum number of columns.  Can only be larger than the current
      52             :     /// number of columns when there are not enough pages to fill all
      53             :     /// available columns.
      54             :     sal_Int32 mnMaxColumnCount;
      55             :     /// The maximum number of rows.  Can only be larger than the current
      56             :     /// number of rows when there are not enough pages to fill all available
      57             :     /// rows.
      58             :     sal_Int32 mnMaxRowCount;
      59             :     Size maPageObjectSize;
      60             :     ::boost::shared_ptr<PageObjectLayouter> mpPageObjectLayouter;
      61             :     ::boost::shared_ptr<view::Theme> mpTheme;
      62             : 
      63             :     /** Specify how the gap between two page objects is associated with the
      64             :       page objects.
      65             :     */
      66             :     enum GapMembership {
      67             :         GM_NONE,       // Gap is not associated with any page object.
      68             :         GM_PREVIOUS,   // The whole gap is associated with the previous page
      69             :                        // object (left or above the gap.)
      70             :         GM_BOTH,       // Half of the gap is associated with previous, half
      71             :                        // with the next page object.
      72             :         GM_NEXT,       // The whole gap is associated with the next page
      73             :                        // object (right or below the gap.)
      74             :         GM_PAGE_BORDER
      75             :     };
      76             : 
      77             :     static Implementation* Create (
      78             :         const Implementation& rImplementation,
      79             :         const Layouter::Orientation eOrientation);
      80             : 
      81             :     virtual Layouter::Orientation GetOrientation() const = 0;
      82             : 
      83             :     bool Rearrange (
      84             :         const Size& rWindowSize,
      85             :         const Size& rPreviewModelSize,
      86             :         const sal_uInt32 nPageCount);
      87             : 
      88             :     /** Calculate the row that the point with the given vertical coordinate
      89             :         is over.  The horizontal component is ignored.
      90             :         @param nYPosition
      91             :             Vertical position in model coordinates.
      92             :         @param bIncludeBordersAndGaps
      93             :             When this flag is <TRUE/> then the area of borders and gaps are
      94             :             interpreted as belonging to one of the rows.
      95             :         @param eGapMembership
      96             :             Specifies to what row the gap areas belong.  Here GM_NONE
      97             :             corresponds to bIncludeBordersAndGaps being <FALSE/>.  When
      98             :             GM_BOTH is given then the upper half is associated to the row
      99             :             above and the lower half to the row below.  Values of
     100             :             GM_PREVIOUS and GM_NEXT associate the whole gap area with the
     101             :             row above or below respectively.
     102             :     */
     103             :     sal_Int32 GetRowAtPosition (
     104             :         sal_Int32 nYPosition,
     105             :         bool bIncludeBordersAndGaps,
     106             :         GapMembership eGapMembership = GM_NONE) const;
     107             : 
     108             :     /** Calculate the column that the point with the given horizontal
     109             :         coordinate is over.  The vertical component is ignored.
     110             :         @param nXPosition
     111             :             Horizontal position in model coordinates.
     112             :         @param bIncludeBordersAndGaps
     113             :             When this flag is <TRUE/> then the area of borders and gaps are
     114             :             interpreted as belonging to one of the columns.
     115             :         @param eGapMembership
     116             :             Specifies to what column the gap areas belong.
     117             :     */
     118             :     sal_Int32 GetColumnAtPosition (
     119             :         sal_Int32 nXPosition,
     120             :         bool bIncludeBordersAndGaps,
     121             :         GapMembership eGapMembership = GM_NONE) const;
     122             : 
     123             :     /** This method is typically called from GetRowAtPosition() and
     124             :         GetColumnAtPosition() to handle a position that lies inside the gap
     125             :         between two adjacent rows or columns.
     126             :         @param nDistanceIntoGap
     127             :             Vertical distance from the bottom of the upper row down into the
     128             :             gap or horizontal distance from the right edge right into the
     129             :             gap.
     130             :         @param eGapMemberhship
     131             :             This value decides what areas in the gap belong to which (or no)
     132             :             row or column.
     133             :         @param nIndex
     134             :             The row index of the upper row or the column index of the left
     135             :             column.
     136             :         @param nGap
     137             :              Width or height of the gap in model coordiantes between the
     138             :              page borders.
     139             :         @return
     140             :            Returns either the index of the upper row (as given as nRow), the
     141             :            index of the lower row (nRow+1) or -1 to indicate that the
     142             :            position belongs to no row.
     143             :         */
     144             :     static sal_Int32 ResolvePositionInGap (
     145             :         sal_Int32 nDistanceIntoGap,
     146             :         GapMembership eGapMembership,
     147             :         sal_Int32 nIndex,
     148             :         sal_Int32 nGap);
     149             : 
     150             :     /** Calculate the logical part of the insert position, i.e. the page
     151             :         after whicht to insert.
     152             :     */
     153             :     virtual void CalculateLogicalInsertPosition (
     154             :         const Point& rModelPosition,
     155             :         InsertPosition& rPosition) const = 0;
     156             : 
     157             :     /** Calculate the geometrical part of the insert position, i.e. the
     158             :         location of where to display the insertion indicator and the
     159             :         distances about which the leading and trailing pages have to be
     160             :         moved to make room for the indicator.
     161             :     */
     162             :     void CalculateGeometricPosition (
     163             :         InsertPosition& rPosition,
     164             :         const Size& rIndicatorSize,
     165             :         const bool bIsVertical,
     166             :         model::SlideSorterModel& rModel) const;
     167             : 
     168             :     /** Return the bounding box of the preview or, when selected, of the page
     169             :         object.  Thus, it returns something like a visual bounding box.
     170             :     */
     171             :     Rectangle GetInnerBoundingBox (
     172             :         model::SlideSorterModel& rModel,
     173             :         const sal_Int32 nIndex) const;
     174             : 
     175             :     Range GetValidHorizontalSizeRange() const;
     176             :     Range GetValidVerticalSizeRange() const;
     177             : 
     178             :     Range GetRangeOfVisiblePageObjects (const Rectangle& aVisibleArea) const;
     179             :     sal_Int32 GetIndex (
     180             :         const sal_Int32 nRow,
     181             :         const sal_Int32 nColumn,
     182             :         const bool bClampToValidRange) const;
     183             : 
     184             :         Rectangle GetPageObjectBox (
     185             :         const sal_Int32 nIndex,
     186             :         const bool bIncludeBorderAndGap = false) const;
     187             : 
     188             :     Rectangle GetPageObjectBox (
     189             :         const sal_Int32 nRow,
     190             :         const sal_Int32 nColumn) const;
     191             : 
     192             :     Rectangle AddBorderAndGap (
     193             :         const Rectangle& rBoundingBox,
     194             :         const sal_Int32 nRow,
     195             :         const sal_Int32 nColumn) const;
     196             : 
     197             :     Rectangle GetTotalBoundingBox() const;
     198             : 
     199             :     virtual ~Implementation();
     200             : 
     201             : protected:
     202             :     Implementation (
     203             :         sd::Window *pWindow,
     204             :         const ::boost::shared_ptr<view::Theme>& rpTheme);
     205             :     Implementation (const Implementation& rImplementation);
     206             : 
     207             :     virtual void CalculateRowAndColumnCount (const Size& rWindowSize) = 0;
     208             :     virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize) = 0;
     209             :     virtual Size CalculateTargetSize (
     210             :         const Size& rWindowSize,
     211             :         const Size& rPreviewModelSize) const = 0;
     212             :     Size GetTargetSize (
     213             :         const Size& rWindowSize,
     214             :         const Size& rPreviewModelSize,
     215             :         const bool bCalculateWidth,
     216             :         const bool bCalculateHeight) const;
     217             :     void CalculateVerticalLogicalInsertPosition (
     218             :         const Point& rModelPosition,
     219             :         InsertPosition& rPosition) const;
     220             : };
     221             : 
     222             : /** The vertical layouter has one column and as many rows as there are
     223             :     pages.
     224             : */
     225         132 : class VerticalImplementation : public Layouter::Implementation
     226             : {
     227             : public:
     228             :     VerticalImplementation (const Implementation& rImplementation);
     229             : 
     230             :     virtual Layouter::Orientation GetOrientation() const SAL_OVERRIDE;
     231             : 
     232             :     void CalculateLogicalInsertPosition (
     233             :         const Point& rModelPosition,
     234             :         InsertPosition& rPosition) const SAL_OVERRIDE;
     235             : 
     236             : protected:
     237             :     virtual void CalculateRowAndColumnCount (const Size& rWindowSize) SAL_OVERRIDE;
     238             :     virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize) SAL_OVERRIDE;
     239             :     virtual Size CalculateTargetSize (
     240             :         const Size& rWindowSize,
     241             :         const Size& rPreviewModelSize) const SAL_OVERRIDE;
     242             : };
     243             : 
     244             : /** The horizontal layouter has one row and as many columns as there are
     245             :     pages.
     246             : */
     247           0 : class HorizontalImplementation : public Layouter::Implementation
     248             : {
     249             : public:
     250             :     HorizontalImplementation (const Implementation& rImplementation);
     251             : 
     252             :     virtual Layouter::Orientation GetOrientation() const SAL_OVERRIDE;
     253             : 
     254             :     void CalculateLogicalInsertPosition (
     255             :         const Point& rModelPosition,
     256             :         InsertPosition& rPosition) const SAL_OVERRIDE;
     257             : 
     258             : protected:
     259             :     virtual void CalculateRowAndColumnCount (const Size& rWindowSize) SAL_OVERRIDE;
     260             :     virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize) SAL_OVERRIDE;
     261             :     virtual Size CalculateTargetSize (
     262             :         const Size& rWindowSize,
     263             :         const Size& rPreviewModelSize) const SAL_OVERRIDE;
     264             : };
     265             : 
     266             : /** The number of columns of the grid layouter is defined via a control in
     267             :     the slide sorter tool bar.  The number of rows is calculated from the
     268             :     number of columns and the number of pages.
     269             : */
     270         260 : class GridImplementation : public Layouter::Implementation
     271             : {
     272             : public:
     273             :     GridImplementation (
     274             :         sd::Window *pWindow,
     275             :         const ::boost::shared_ptr<view::Theme>& rpTheme);
     276             :     GridImplementation (const Implementation& rImplementation);
     277             : 
     278             :     virtual Layouter::Orientation GetOrientation() const SAL_OVERRIDE;
     279             : 
     280             :     void CalculateLogicalInsertPosition (
     281             :         const Point& rModelPosition,
     282             :         InsertPosition& rPosition) const SAL_OVERRIDE;
     283             : 
     284             : protected:
     285             :     virtual void CalculateRowAndColumnCount (const Size& rWindowSize) SAL_OVERRIDE;
     286             :     virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize) SAL_OVERRIDE;
     287             :     virtual Size CalculateTargetSize (
     288             :         const Size& rWindowSize,
     289             :         const Size& rPreviewModelSize) const SAL_OVERRIDE;
     290             : };
     291             : 
     292             : //===== Layouter ==============================================================
     293             : 
     294          64 : Layouter::Layouter (
     295             :     sd::Window *pWindow,
     296             :     const ::boost::shared_ptr<Theme>& rpTheme)
     297          64 :     : mpImplementation(new GridImplementation(pWindow, rpTheme)),
     298         128 :       mpWindow(pWindow)
     299             : {
     300          64 : }
     301             : 
     302          64 : Layouter::~Layouter()
     303             : {
     304          64 : }
     305             : 
     306         962 : ::boost::shared_ptr<PageObjectLayouter> Layouter::GetPageObjectLayouter() const
     307             : {
     308         962 :     return mpImplementation->mpPageObjectLayouter;
     309             : }
     310             : 
     311           0 : void Layouter::SetColumnCount (
     312             :     sal_Int32 nMinimalColumnCount,
     313             :         sal_Int32 nMaximalColumnCount)
     314             : {
     315           0 :     if (nMinimalColumnCount <= nMaximalColumnCount)
     316             :     {
     317           0 :         mpImplementation->mnMinimalColumnCount = nMinimalColumnCount;
     318           0 :         mpImplementation->mnMaximalColumnCount = nMaximalColumnCount;
     319             :     }
     320           0 : }
     321             : 
     322         326 : bool Layouter::Rearrange (
     323             :     const Orientation eOrientation,
     324             :     const Size& rWindowSize,
     325             :     const Size& rPageSize,
     326             :     const sal_uInt32 nPageCount)
     327             : {
     328             :     OSL_ASSERT(mpWindow);
     329             : 
     330         326 :     if (eOrientation != mpImplementation->GetOrientation())
     331         132 :         mpImplementation.reset(Implementation::Create(*mpImplementation, eOrientation));
     332             : 
     333         326 :     return mpImplementation->Rearrange(rWindowSize, rPageSize, nPageCount);
     334             : }
     335             : 
     336         192 : sal_Int32 Layouter::GetColumnCount() const
     337             : {
     338         192 :     return mpImplementation->mnColumnCount;
     339             : }
     340             : 
     341           0 : sal_Int32 Layouter::GetIndex (const sal_Int32 nRow, const sal_Int32 nColumn) const
     342             : {
     343           0 :     return mpImplementation->GetIndex(nRow,nColumn,true);
     344             : }
     345             : 
     346          64 : Size Layouter::GetPageObjectSize() const
     347             : {
     348          64 :     return mpImplementation->maPageObjectSize;
     349             : }
     350             : 
     351         433 : Rectangle Layouter::GetPageObjectBox (
     352             :     const sal_Int32 nIndex,
     353             :     const bool bIncludeBorderAndGap) const
     354             : {
     355         433 :     return mpImplementation->GetPageObjectBox(nIndex, bIncludeBorderAndGap);
     356             : }
     357             : 
     358         875 : Rectangle Layouter::GetTotalBoundingBox() const
     359             : {
     360         875 :     return mpImplementation->GetTotalBoundingBox();
     361             : }
     362             : 
     363           0 : InsertPosition Layouter::GetInsertPosition (
     364             :     const Point& rModelPosition,
     365             :     const Size& rIndicatorSize,
     366             :     model::SlideSorterModel& rModel) const
     367             : {
     368           0 :     InsertPosition aPosition;
     369           0 :     mpImplementation->CalculateLogicalInsertPosition(
     370             :         rModelPosition,
     371           0 :         aPosition);
     372             :     mpImplementation->CalculateGeometricPosition(
     373             :         aPosition,
     374             :         rIndicatorSize,
     375           0 :         GetColumnCount()==1,
     376           0 :         rModel);
     377           0 :     return aPosition;
     378             : }
     379             : 
     380          66 : Range Layouter::GetValidHorizontalSizeRange() const
     381             : {
     382          66 :     return mpImplementation->GetValidHorizontalSizeRange();
     383             : }
     384             : 
     385           0 : Range Layouter::GetValidVerticalSizeRange() const
     386             : {
     387           0 :     return mpImplementation->GetValidVerticalSizeRange();
     388             : }
     389             : 
     390         383 : Range Layouter::GetRangeOfVisiblePageObjects (const Rectangle& aVisibleArea) const
     391             : {
     392         383 :     return mpImplementation->GetRangeOfVisiblePageObjects(aVisibleArea);
     393             : }
     394             : 
     395          68 : sal_Int32 Layouter::GetIndexAtPoint (
     396             :     const Point& rPosition,
     397             :     const bool bIncludePageBorders,
     398             :     const bool bClampToValidRange) const
     399             : {
     400             :     const sal_Int32 nRow (
     401             :         mpImplementation->GetRowAtPosition (
     402          68 :             rPosition.Y(),
     403             :             bIncludePageBorders,
     404         136 :             bIncludePageBorders ? Implementation::GM_PAGE_BORDER : Implementation::GM_NONE));
     405             :     const sal_Int32 nColumn (
     406             :         mpImplementation->GetColumnAtPosition (
     407          68 :             rPosition.X(),
     408             :             bIncludePageBorders,
     409         136 :             bIncludePageBorders ? Implementation::GM_PAGE_BORDER : Implementation::GM_NONE));
     410             : 
     411          68 :     return mpImplementation->GetIndex(nRow,nColumn,bClampToValidRange);
     412             : }
     413             : 
     414             : //===== Layouter::Implementation ==============================================
     415             : 
     416         132 : Layouter::Implementation* Layouter::Implementation::Create (
     417             :     const Implementation& rImplementation,
     418             :     const Layouter::Orientation eOrientation)
     419             : {
     420         132 :     switch (eOrientation)
     421             :     {
     422           0 :         case HORIZONTAL: return new HorizontalImplementation(rImplementation);
     423          66 :         case VERTICAL: return new VerticalImplementation(rImplementation);
     424             :         case GRID:
     425          66 :         default: return new GridImplementation(rImplementation);
     426             :     }
     427             : }
     428             : 
     429          64 : Layouter::Implementation::Implementation (
     430             :     sd::Window *pWindow,
     431             :     const ::boost::shared_ptr<view::Theme>& rpTheme)
     432             :     : mpWindow(pWindow),
     433             :       mnRequestedLeftBorder(5),
     434             :       mnRequestedRightBorder(5),
     435             :       mnRequestedTopBorder(5),
     436             :       mnRequestedBottomBorder(5),
     437             :       mnLeftBorder(5),
     438             :       mnRightBorder(5),
     439             :       mnTopBorder(5),
     440             :       mnBottomBorder(5),
     441             :       mnVerticalGap (10 - 2*Theme_FocusIndicatorWidth),
     442             :       mnHorizontalGap(10 - 2*Theme_FocusIndicatorWidth),
     443             :       maMinimalSize(132,98),
     444             :       maPreferredSize(200,150),
     445             :       maMaximalSize(600,400),
     446             :       mnMinimalColumnCount(1),
     447             :       mnMaximalColumnCount(15),
     448             :       mnPageCount(0),
     449             :       mnColumnCount(1),
     450             :       mnRowCount(0),
     451             :       mnMaxColumnCount(0),
     452             :       mnMaxRowCount(0),
     453             :       maPageObjectSize(1,1),
     454             :       mpPageObjectLayouter(),
     455          64 :       mpTheme(rpTheme)
     456             : {
     457          64 : }
     458             : 
     459         132 : Layouter::Implementation::Implementation (const Implementation& rImplementation)
     460             :     : mpWindow(rImplementation.mpWindow),
     461             :       mnRequestedLeftBorder(rImplementation.mnRequestedLeftBorder),
     462             :       mnRequestedRightBorder(rImplementation.mnRequestedRightBorder),
     463             :       mnRequestedTopBorder(rImplementation.mnRequestedTopBorder),
     464             :       mnRequestedBottomBorder(rImplementation.mnRequestedBottomBorder),
     465             :       mnLeftBorder(rImplementation.mnLeftBorder),
     466             :       mnRightBorder(rImplementation.mnRightBorder),
     467             :       mnTopBorder(rImplementation.mnTopBorder),
     468             :       mnBottomBorder(rImplementation.mnBottomBorder),
     469             :       mnVerticalGap(rImplementation.mnVerticalGap),
     470             :       mnHorizontalGap(rImplementation.mnHorizontalGap),
     471             :       maMinimalSize(rImplementation.maMinimalSize),
     472             :       maPreferredSize(rImplementation.maPreferredSize),
     473             :       maMaximalSize(rImplementation.maMaximalSize),
     474             :       mnMinimalColumnCount(rImplementation.mnMinimalColumnCount),
     475             :       mnMaximalColumnCount(rImplementation.mnMaximalColumnCount),
     476             :       mnPageCount(rImplementation.mnPageCount),
     477             :       mnColumnCount(rImplementation.mnColumnCount),
     478             :       mnRowCount(rImplementation.mnRowCount),
     479             :       mnMaxColumnCount(rImplementation.mnMaxColumnCount),
     480             :       mnMaxRowCount(rImplementation.mnMaxRowCount),
     481             :       maPageObjectSize(rImplementation.maPageObjectSize),
     482             :       mpPageObjectLayouter(),
     483         132 :       mpTheme(rImplementation.mpTheme)
     484             : {
     485         132 : }
     486             : 
     487         196 : Layouter::Implementation::~Implementation()
     488             : {
     489         196 : }
     490             : 
     491         326 : bool Layouter::Implementation::Rearrange (
     492             :     const Size& rWindowSize,
     493             :     const Size& rPreviewModelSize,
     494             :     const sal_uInt32 nPageCount)
     495             : {
     496         326 :     mnPageCount = nPageCount;
     497             : 
     498             :     // Return early when the window or the model have not yet been initialized.
     499         326 :     if (rWindowSize.Width()<=0 || rWindowSize.Height()<=0)
     500           0 :         return false;
     501         326 :     if (rPreviewModelSize.Width()<=0 || rPreviewModelSize.Height()<=0)
     502           0 :         return false;
     503             : 
     504         326 :     CalculateRowAndColumnCount(rWindowSize);
     505             : 
     506             :     // Update the border values.
     507         326 :     mnLeftBorder = mnRequestedLeftBorder;
     508         326 :     mnTopBorder = mnRequestedTopBorder;
     509         326 :     mnRightBorder = mnRequestedRightBorder;
     510         326 :     mnBottomBorder = mnRequestedBottomBorder;
     511         326 :     if (mnColumnCount > 1)
     512             :     {
     513           0 :         int nMinimumBorderWidth = mnHorizontalGap/2;
     514           0 :         if (mnLeftBorder < nMinimumBorderWidth)
     515           0 :             mnLeftBorder = nMinimumBorderWidth;
     516           0 :         if (mnRightBorder < nMinimumBorderWidth)
     517           0 :             mnRightBorder = nMinimumBorderWidth;
     518             :     }
     519             :     else
     520             :     {
     521         326 :         int nMinimumBorderHeight = mnVerticalGap/2;
     522         326 :         if (mnTopBorder < nMinimumBorderHeight)
     523           0 :             mnTopBorder = nMinimumBorderHeight;
     524         326 :         if (mnBottomBorder < nMinimumBorderHeight)
     525           0 :             mnBottomBorder = nMinimumBorderHeight;
     526             :     }
     527             : 
     528             :     mpPageObjectLayouter.reset(
     529             :         new PageObjectLayouter(
     530         326 :             CalculateTargetSize(rWindowSize, rPreviewModelSize),
     531             :             rPreviewModelSize,
     532             :             mpWindow,
     533         326 :             mnPageCount));
     534             : 
     535             :     maPageObjectSize = mpPageObjectLayouter->GetGridMaxSize(
     536         326 :         PageObjectLayouter::WindowCoordinateSystem);
     537             : 
     538         326 :     CalculateMaxRowAndColumnCount(rWindowSize);
     539             : 
     540         326 :     return true;
     541             : }
     542             : 
     543         834 : sal_Int32 Layouter::Implementation::GetRowAtPosition (
     544             :     sal_Int32 nYPosition,
     545             :     bool bIncludeBordersAndGaps,
     546             :     GapMembership eGapMembership) const
     547             : {
     548         834 :     sal_Int32 nRow = -1;
     549             : 
     550         834 :     const sal_Int32 nY = nYPosition - mnTopBorder;
     551         834 :     if (nY >= 0)
     552             :     {
     553             :         // Vertical distance from one row to the next.
     554         511 :         const sal_Int32 nRowOffset (maPageObjectSize.Height() + mnVerticalGap);
     555             : 
     556             :         // Calculate row consisting of page objects and gap below.
     557         511 :         nRow = nY / nRowOffset;
     558             : 
     559         511 :         const sal_Int32 nDistanceIntoGap ((nY - nRow*nRowOffset) - maPageObjectSize.Height());
     560             :         // When inside the gap below then nYPosition is not over a page
     561             :         // object.
     562         511 :         if (nDistanceIntoGap > 0)
     563             :         {
     564             :             sal_Int32 nResolvedRow = ResolvePositionInGap(
     565             :                 nDistanceIntoGap,
     566             :                 eGapMembership,
     567             :                 nRow,
     568           0 :                 mnVerticalGap);
     569           0 :             if (!bIncludeBordersAndGaps || nResolvedRow != -1)
     570           0 :                 nRow = nResolvedRow;
     571             :         }
     572             :     }
     573         323 :     else if (bIncludeBordersAndGaps)
     574             :     {
     575             :         // We are in the top border area.  Set nRow to the first row when
     576             :         // the top border shall be considered to belong to the first row.
     577         255 :         nRow = 0;
     578             :     }
     579             : 
     580         834 :     return nRow;
     581             : }
     582             : 
     583         834 : sal_Int32 Layouter::Implementation::GetColumnAtPosition (
     584             :     sal_Int32 nXPosition,
     585             :     bool bIncludeBordersAndGaps,
     586             :     GapMembership eGapMembership) const
     587             : {
     588         834 :     sal_Int32 nColumn = -1;
     589             : 
     590         834 :     sal_Int32 nX = nXPosition - mnLeftBorder;
     591         834 :     if (nX >= 0)
     592             :     {
     593             :         // Horizontal distance from one column to the next.
     594         511 :         const sal_Int32 nColumnOffset (maPageObjectSize.Width() + mnHorizontalGap);
     595             : 
     596             :         // Calculate row consisting of page objects and gap below.
     597         511 :         nColumn = nX / nColumnOffset;
     598         511 :         if (nColumn < 0)
     599           0 :             nColumn = 0;
     600         511 :         else if (nColumn >= mnColumnCount)
     601         255 :             nColumn = mnColumnCount-1;
     602             : 
     603         511 :         const sal_Int32 nDistanceIntoGap ((nX - nColumn*nColumnOffset) - maPageObjectSize.Width());
     604             :         // When inside the gap at the right then nXPosition is not over a
     605             :         // page object.
     606         511 :         if (nDistanceIntoGap > 0)
     607             :         {
     608             :             sal_Int32 nResolvedColumn = ResolvePositionInGap(
     609             :                 nDistanceIntoGap,
     610             :                 eGapMembership,
     611             :                 nColumn,
     612         255 :                 mnHorizontalGap);
     613         255 :             if (!bIncludeBordersAndGaps || nResolvedColumn != -1)
     614         255 :                 nColumn = nResolvedColumn;
     615             :         }
     616             :     }
     617         323 :     else if (bIncludeBordersAndGaps)
     618             :     {
     619             :         // We are in the left border area.  Set nColumn to the first column
     620             :         // when the left border shall be considered to belong to the first
     621             :         // column.
     622         255 :         nColumn = 0;
     623             :     }
     624         834 :     return nColumn;
     625             : }
     626             : 
     627         255 : sal_Int32 Layouter::Implementation::ResolvePositionInGap (
     628             :     sal_Int32 nDistanceIntoGap,
     629             :     GapMembership eGapMembership,
     630             :     sal_Int32 nIndex,
     631             :     sal_Int32 nGap)
     632             : {
     633         255 :     switch (eGapMembership)
     634             :     {
     635             :         case GM_NONE:
     636             :             // The gap is no man's land.
     637           0 :             nIndex = -1;
     638           0 :             break;
     639             : 
     640             :         case GM_BOTH:
     641             :         {
     642             :             // The lower half of the gap belongs to the next row or column.
     643           0 :             sal_Int32 nFirstHalfGapWidth = nGap / 2;
     644           0 :             if (nDistanceIntoGap > nFirstHalfGapWidth)
     645           0 :                 nIndex ++;
     646           0 :             break;
     647             :         }
     648             : 
     649             :         case GM_PREVIOUS:
     650             :             // Row or column already at correct value.
     651         255 :             break;
     652             : 
     653             :         case GM_NEXT:
     654             :             // The complete gap belongs to the next row or column.
     655           0 :             nIndex ++;
     656           0 :             break;
     657             : 
     658             :         case GM_PAGE_BORDER:
     659           0 :             if (nDistanceIntoGap > 0)
     660             :             {
     661           0 :                 if (nDistanceIntoGap > nGap)
     662             :                 {
     663             :                     // Inside the border of the next row or column.
     664           0 :                     nIndex ++;
     665             :                 }
     666             :                 else
     667             :                 {
     668             :                     // Inside the gap between the page borders.
     669           0 :                     nIndex = -1;
     670             :                 }
     671             :             }
     672           0 :             break;
     673             : 
     674             :         default:
     675           0 :             nIndex = -1;
     676             :     }
     677             : 
     678         255 :     return nIndex;
     679             : }
     680             : 
     681           0 : void Layouter::Implementation::CalculateGeometricPosition (
     682             :     InsertPosition& rPosition,
     683             :     const Size& rIndicatorSize,
     684             :     const bool bIsVertical,
     685             :     model::SlideSorterModel& rModel) const
     686             : {
     687             :     // 1. Determine right/bottom of the leading page and the left/top of the
     688             :     // trailing page object and how to distribute the missing space.
     689           0 :     sal_Int32 nLeadingLocation (0);
     690           0 :     sal_Int32 nTrailingLocation (0);
     691           0 :     bool bIsLeadingFixed (false);
     692           0 :     bool bIsTrailingFixed (false);
     693           0 :     sal_Int32 nSecondaryLocation (0);
     694           0 :     const sal_Int32 nIndex (rPosition.GetIndex());
     695             : 
     696           0 :     if (rPosition.IsAtRunStart())
     697             :     {
     698             :         // Place indicator at the top of the column.
     699           0 :         const Rectangle aOuterBox (GetPageObjectBox(nIndex));
     700           0 :         const Rectangle aInnerBox (GetInnerBoundingBox(rModel, nIndex));
     701           0 :         if (bIsVertical)
     702             :         {
     703           0 :             nLeadingLocation = aOuterBox.Top();
     704           0 :             nTrailingLocation = aInnerBox.Top();
     705           0 :             nSecondaryLocation = aInnerBox.Center().X();
     706             :         }
     707             :         else
     708             :         {
     709           0 :             nLeadingLocation = aOuterBox.Left();
     710           0 :             nTrailingLocation = aInnerBox.Left();
     711           0 :             nSecondaryLocation = aInnerBox.Center().Y();
     712             :         }
     713           0 :         bIsLeadingFixed = true;
     714             :     }
     715           0 :     else if (rPosition.IsAtRunEnd())
     716             :     {
     717             :         // Place indicator at the bottom/right of the column/row.
     718             : 
     719           0 :         const Rectangle aOuterBox (GetPageObjectBox(nIndex-1));
     720           0 :         const Rectangle aInnerBox (GetInnerBoundingBox(rModel, nIndex-1));
     721           0 :         if (bIsVertical)
     722             :         {
     723           0 :             nLeadingLocation = aInnerBox.Bottom();
     724           0 :             nTrailingLocation = aOuterBox.Bottom();
     725           0 :             nSecondaryLocation = aInnerBox.Center().X();
     726             :         }
     727             :         else
     728             :         {
     729           0 :             nLeadingLocation = aInnerBox.Right();
     730           0 :             nTrailingLocation = aOuterBox.Right();
     731           0 :             nSecondaryLocation = aInnerBox.Center().Y();
     732             :         }
     733           0 :         bIsTrailingFixed = true;
     734           0 :         if ( ! rPosition.IsExtraSpaceNeeded())
     735           0 :             bIsLeadingFixed = true;
     736             :     }
     737             :     else
     738             :     {
     739             :         // Place indicator between two rows/columns.
     740           0 :         const Rectangle aBox1 (GetInnerBoundingBox(rModel, nIndex-1));
     741           0 :         const Rectangle aBox2 (GetInnerBoundingBox(rModel, nIndex));
     742           0 :         if (bIsVertical)
     743             :         {
     744           0 :             nLeadingLocation = aBox1.Bottom();
     745           0 :             nTrailingLocation = aBox2.Top();
     746           0 :             nSecondaryLocation = (aBox1.Center().X() + aBox2.Center().X()) / 2;
     747             :         }
     748             :         else
     749             :         {
     750           0 :             nLeadingLocation = aBox1.Right();
     751           0 :             nTrailingLocation = aBox2.Left();
     752           0 :             nSecondaryLocation = (aBox1.Center().Y() + aBox2.Center().Y()) / 2;
     753             :         }
     754             :     }
     755             : 
     756             :     // 2. Calculate the location of the insert indicator and the offsets of
     757             :     // leading and trailing pages.
     758           0 :     const sal_Int32 nAvailableSpace (nTrailingLocation - nLeadingLocation);
     759           0 :     const sal_Int32 nRequiredSpace (bIsVertical ? rIndicatorSize.Height():rIndicatorSize.Width());
     760           0 :     const sal_Int32 nMissingSpace (::std::max(sal_Int32(0), nRequiredSpace - nAvailableSpace));
     761           0 :     sal_Int32 nPrimaryLocation (0);
     762           0 :     sal_Int32 nLeadingOffset (0);
     763           0 :     sal_Int32 nTrailingOffset (0);
     764           0 :     if (bIsLeadingFixed)
     765             :     {
     766           0 :         nPrimaryLocation = nLeadingLocation + nRequiredSpace/2;
     767           0 :         if ( ! bIsTrailingFixed)
     768           0 :             nTrailingOffset = nMissingSpace;
     769             :     }
     770           0 :     else if (bIsTrailingFixed)
     771             :     {
     772           0 :         nPrimaryLocation = nTrailingLocation - nRequiredSpace/2;
     773           0 :         nLeadingOffset = -nMissingSpace;
     774             :     }
     775             :     else
     776             :     {
     777           0 :         nPrimaryLocation = (nLeadingLocation + nTrailingLocation) /2;
     778           0 :         nLeadingOffset = -nMissingSpace/2;
     779           0 :         nTrailingOffset = nMissingSpace + nLeadingOffset;
     780             :     }
     781             : 
     782           0 :     if (bIsVertical)
     783             :     {
     784             :         rPosition.SetGeometricalPosition(
     785             :             Point(nSecondaryLocation, nPrimaryLocation),
     786             :             Point(0, nLeadingOffset),
     787           0 :             Point(0, nTrailingOffset));
     788             :     }
     789             :     else
     790             :     {
     791             :         rPosition.SetGeometricalPosition(
     792             :             Point(nPrimaryLocation, nSecondaryLocation),
     793             :             Point(nLeadingOffset, 0),
     794           0 :             Point(nTrailingOffset, 0));
     795             :     }
     796           0 : }
     797             : 
     798           0 : Rectangle Layouter::Implementation::GetInnerBoundingBox (
     799             :     model::SlideSorterModel& rModel,
     800             :     const sal_Int32 nIndex) const
     801             : {
     802           0 :     model::SharedPageDescriptor pDescriptor (rModel.GetPageDescriptor(nIndex));
     803           0 :     if ( ! pDescriptor)
     804           0 :         return Rectangle();
     805             : 
     806           0 :     PageObjectLayouter::Part ePart = PageObjectLayouter::Preview;
     807             : 
     808           0 :     if (pDescriptor->HasState(model::PageDescriptor::ST_Selected))
     809           0 :         ePart = PageObjectLayouter::PageObject;
     810             : 
     811             :     return mpPageObjectLayouter->GetBoundingBox(
     812             :             pDescriptor, ePart,
     813           0 :             PageObjectLayouter::ModelCoordinateSystem, true);
     814             : }
     815             : 
     816          66 : Range Layouter::Implementation::GetValidHorizontalSizeRange() const
     817             : {
     818             :     return Range(
     819          66 :         mnLeftBorder + maMinimalSize.Width() + mnRightBorder,
     820         132 :         mnLeftBorder + maMaximalSize.Width() + mnRightBorder);
     821             : }
     822             : 
     823           0 : Range Layouter::Implementation::GetValidVerticalSizeRange() const
     824             : {
     825             :     return Range(
     826           0 :         mnTopBorder + maMinimalSize.Height() + mnBottomBorder,
     827           0 :         mnTopBorder + maMaximalSize.Height() + mnBottomBorder);
     828             : }
     829             : 
     830         383 : Range Layouter::Implementation::GetRangeOfVisiblePageObjects (const Rectangle& aVisibleArea) const
     831             : {
     832         383 :     const sal_Int32 nRow0 (GetRowAtPosition(aVisibleArea.Top(), true, GM_NEXT));
     833         383 :     const sal_Int32 nCol0 (GetColumnAtPosition(aVisibleArea.Left(),true, GM_NEXT));
     834         383 :     const sal_Int32 nRow1 (GetRowAtPosition(aVisibleArea.Bottom(), true, GM_PREVIOUS));
     835         383 :     const sal_Int32 nCol1 (GetColumnAtPosition(aVisibleArea.Right(), true, GM_PREVIOUS));
     836             : 
     837             :     // When start and end lie in different rows then the range may include
     838             :     // slides outside (left or right of) the given area.
     839         383 :     return Range(GetIndex(nRow0,nCol0,true), GetIndex(nRow1,nCol1,true));
     840             : }
     841             : 
     842         326 : Size Layouter::Implementation::GetTargetSize (
     843             :     const Size& rWindowSize,
     844             :     const Size& rPreviewModelSize,
     845             :     const bool bCalculateWidth,
     846             :     const bool bCalculateHeight) const
     847             : {
     848             :     (void)rPreviewModelSize;
     849             : 
     850         326 :     if (mnColumnCount<=0 || mnRowCount<=0)
     851           0 :         return maPreferredSize;
     852         326 :     if ( ! (bCalculateWidth || bCalculateHeight))
     853             :     {
     854             :         OSL_ASSERT(bCalculateWidth || bCalculateHeight);
     855           0 :         return maPreferredSize;
     856             :     }
     857             : 
     858             :     // Calculate the width of each page object.
     859         326 :     Size aTargetSize (0,0);
     860         326 :     if (bCalculateWidth)
     861             :         aTargetSize.setWidth(
     862         326 :             (rWindowSize.Width() - mnLeftBorder - mnRightBorder
     863         326 :                 - (mnColumnCount-1) * mnHorizontalGap)
     864         326 :                     / mnColumnCount);
     865           0 :     else if (bCalculateHeight)
     866             :         aTargetSize.setHeight(
     867           0 :             (rWindowSize.Height() - mnTopBorder - mnBottomBorder
     868           0 :                 - (mnRowCount-1) * mnVerticalGap)
     869           0 :                     / mnRowCount);
     870             : 
     871         326 :     if (bCalculateWidth)
     872             :     {
     873         326 :         if (aTargetSize.Width() < maMinimalSize.Width())
     874           0 :             aTargetSize.setWidth(maMinimalSize.Width());
     875         326 :         else if (aTargetSize.Width() > maMaximalSize.Width())
     876           0 :             aTargetSize.setWidth(maMaximalSize.Width());
     877             :     }
     878           0 :     else if (bCalculateHeight)
     879             :     {
     880           0 :         if (aTargetSize.Height() < maMinimalSize.Height())
     881           0 :             aTargetSize.setHeight(maMinimalSize.Height());
     882           0 :         else if (aTargetSize.Height() > maMaximalSize.Height())
     883           0 :             aTargetSize.setHeight(maMaximalSize.Height());
     884             :     }
     885             : 
     886         326 :     return aTargetSize;
     887             : }
     888             : 
     889         834 : sal_Int32 Layouter::Implementation::GetIndex (
     890             :     const sal_Int32 nRow,
     891             :     const sal_Int32 nColumn,
     892             :     const bool bClampToValidRange) const
     893             : {
     894         834 :     if (nRow >= 0 && nColumn >= 0)
     895             :     {
     896         766 :         const sal_Int32 nIndex (nRow * mnColumnCount + nColumn);
     897         766 :         if (nIndex >= mnPageCount)
     898         253 :             if (bClampToValidRange)
     899         253 :                 return mnPageCount-1;
     900             :             else
     901           0 :                 return -1;
     902             :         else
     903         513 :             return nIndex;
     904             :     }
     905          68 :     else if (bClampToValidRange)
     906           0 :         return 0;
     907             :     else
     908          68 :         return -1;
     909             : }
     910             : 
     911         433 : Rectangle Layouter::Implementation::GetPageObjectBox (
     912             :     const sal_Int32 nIndex,
     913             :     const bool bIncludeBorderAndGap) const
     914             : {
     915         433 :     const sal_Int32 nRow (nIndex / mnColumnCount);
     916         433 :     const sal_Int32 nColumn (nIndex % mnColumnCount);
     917             : 
     918         433 :     const Rectangle aBoundingBox (GetPageObjectBox(nRow,nColumn));
     919         433 :     if (bIncludeBorderAndGap)
     920         237 :         return AddBorderAndGap(aBoundingBox, nRow, nColumn);
     921             :     else
     922         196 :         return aBoundingBox;
     923             : }
     924             : 
     925         433 : Rectangle Layouter::Implementation::GetPageObjectBox (
     926             :     const sal_Int32 nRow,
     927             :     const sal_Int32 nColumn) const
     928             : {
     929             :     return Rectangle(
     930             :         Point (mnLeftBorder
     931         433 :             + nColumn * maPageObjectSize.Width()
     932         433 :             + (nColumn>0 ? nColumn : 0) * mnHorizontalGap,
     933             :             mnTopBorder
     934         433 :             + nRow * maPageObjectSize.Height()
     935         433 :             + (nRow>0 ? nRow : 0) * mnVerticalGap),
     936        1299 :         maPageObjectSize);
     937             : }
     938             : 
     939         237 : Rectangle Layouter::Implementation::AddBorderAndGap (
     940             :     const Rectangle& rBoundingBox,
     941             :     const sal_Int32 nRow,
     942             :     const sal_Int32 nColumn) const
     943             : {
     944         237 :     Rectangle aBoundingBox (rBoundingBox);
     945             : 
     946         237 :     if (nColumn == 0)
     947         237 :         aBoundingBox.Left() = 0;
     948             :     else
     949           0 :         aBoundingBox.Left() -= mnHorizontalGap/2;
     950         237 :     if (nColumn == mnColumnCount-1)
     951         237 :         aBoundingBox.Right() += mnRightBorder;
     952             :     else
     953           0 :         aBoundingBox.Right() += mnHorizontalGap/2;
     954         237 :     if (nRow == 0)
     955         222 :         aBoundingBox.Top() = 0;
     956             :     else
     957          15 :         aBoundingBox.Top() -= mnVerticalGap/2;
     958         237 :     if (nRow == mnRowCount-1)
     959         144 :         aBoundingBox.Bottom() += mnBottomBorder;
     960             :     else
     961          93 :         aBoundingBox.Bottom() += mnVerticalGap/2;
     962         237 :     return aBoundingBox;
     963             : }
     964             : 
     965         875 : Rectangle Layouter::Implementation::GetTotalBoundingBox() const
     966             : {
     967         875 :     sal_Int32 nHorizontalSize = 0;
     968         875 :     sal_Int32 nVerticalSize = 0;
     969         875 :     if (mnColumnCount > 0)
     970             :     {
     971         875 :         sal_Int32 nRowCount = (mnPageCount+mnColumnCount-1) / mnColumnCount;
     972             :         nHorizontalSize =
     973             :             mnLeftBorder
     974         875 :             + mnRightBorder
     975         875 :             + mnColumnCount * maPageObjectSize.Width();
     976         875 :         if (mnColumnCount > 1)
     977           0 :             nHorizontalSize +=  (mnColumnCount-1) * mnHorizontalGap;
     978             :         nVerticalSize =
     979             :             mnTopBorder
     980         875 :             + mnBottomBorder
     981         875 :             + nRowCount * maPageObjectSize.Height();
     982         875 :         if (nRowCount > 1)
     983         134 :             nVerticalSize += (nRowCount-1) * mnVerticalGap;
     984             :     }
     985             : 
     986             :     return Rectangle (
     987             :         Point(0,0),
     988             :         Size (nHorizontalSize, nVerticalSize)
     989         875 :         );
     990             : }
     991             : 
     992           0 : void Layouter::Implementation::CalculateVerticalLogicalInsertPosition (
     993             :     const Point& rModelPosition,
     994             :     InsertPosition& rPosition) const
     995             : {
     996           0 :     const sal_Int32 nY = rModelPosition.Y() - mnTopBorder + maPageObjectSize.Height()/2;
     997           0 :     const sal_Int32 nRowHeight (maPageObjectSize.Height() + mnVerticalGap);
     998           0 :     const sal_Int32 nRow (::std::min(mnPageCount, nY / nRowHeight));
     999             :     rPosition.SetLogicalPosition (
    1000             :         nRow,
    1001             :         0,
    1002             :         nRow,
    1003             :         (nRow == 0),
    1004             :         (nRow == mnRowCount),
    1005           0 :         (nRow >= mnMaxRowCount));
    1006           0 : }
    1007             : 
    1008             : //===== HorizontalImplementation ================================================
    1009             : 
    1010           0 : HorizontalImplementation::HorizontalImplementation (const Implementation& rImplementation)
    1011           0 :     : Implementation(rImplementation)
    1012             : {
    1013           0 : }
    1014             : 
    1015           0 : Layouter::Orientation HorizontalImplementation::GetOrientation() const
    1016             : {
    1017           0 :     return Layouter::HORIZONTAL;
    1018             : }
    1019             : 
    1020           0 : void HorizontalImplementation::CalculateRowAndColumnCount (const Size& rWindowSize)
    1021             : {
    1022             :     (void)rWindowSize;
    1023             : 
    1024             :     // Row and column count are fixed (for a given page count.)
    1025           0 :     mnColumnCount = mnPageCount;
    1026           0 :     mnRowCount = 1;
    1027           0 : }
    1028             : 
    1029           0 : void HorizontalImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
    1030             : {
    1031           0 :     mnMaxColumnCount = (rWindowSize.Width() - mnLeftBorder - mnRightBorder)
    1032           0 :         / (maPageObjectSize.Width()  + mnHorizontalGap);
    1033           0 :     mnMaxRowCount = 1;
    1034           0 : }
    1035             : 
    1036           0 : Size HorizontalImplementation::CalculateTargetSize (
    1037             :     const Size& rWindowSize,
    1038             :     const Size& rPreviewModelSize) const
    1039             : {
    1040           0 :     return Implementation::GetTargetSize(rWindowSize, rPreviewModelSize, false, true);
    1041             : }
    1042             : 
    1043           0 : void HorizontalImplementation::CalculateLogicalInsertPosition (
    1044             :     const Point& rModelPosition,
    1045             :     InsertPosition& rPosition) const
    1046             : {
    1047           0 :     const sal_Int32 nX = rModelPosition.X() - mnLeftBorder + maPageObjectSize.Width()/2;
    1048           0 :     const sal_Int32 nColumnWidth (maPageObjectSize.Width() + mnHorizontalGap);
    1049           0 :     const sal_Int32 nColumn (::std::min(mnPageCount, nX / nColumnWidth));
    1050             :     rPosition.SetLogicalPosition (
    1051             :         0,
    1052             :         nColumn,
    1053             :         nColumn,
    1054             :         (nColumn == 0),
    1055             :         (nColumn == mnColumnCount),
    1056           0 :         (nColumn >= mnMaxColumnCount));
    1057           0 : }
    1058             : 
    1059             : //===== VerticalImplementation ================================================
    1060             : 
    1061          66 : VerticalImplementation::VerticalImplementation (const Implementation& rImplementation)
    1062          66 :     : Implementation(rImplementation)
    1063             : {
    1064          66 : }
    1065             : 
    1066         188 : Layouter::Orientation VerticalImplementation::GetOrientation() const
    1067             : {
    1068         188 :     return Layouter::VERTICAL;
    1069             : }
    1070             : 
    1071         188 : void VerticalImplementation::CalculateRowAndColumnCount (const Size& rWindowSize)
    1072             : {
    1073             :     (void)rWindowSize;
    1074             : 
    1075             :     // Row and column count are fixed (for a given page count.)
    1076         188 :     mnRowCount = mnPageCount;
    1077         188 :     mnColumnCount = 1;
    1078             : 
    1079         188 : }
    1080             : 
    1081         188 : void VerticalImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
    1082             : {
    1083         188 :     mnMaxRowCount = (rWindowSize.Height() - mnTopBorder - mnBottomBorder)
    1084         188 :         / (maPageObjectSize.Height()  + mnVerticalGap);
    1085         188 :     mnMaxColumnCount = 1;
    1086         188 : }
    1087             : 
    1088         188 : Size VerticalImplementation::CalculateTargetSize (
    1089             :     const Size& rWindowSize,
    1090             :     const Size& rPreviewModelSize) const
    1091             : {
    1092         188 :     return Implementation::GetTargetSize(rWindowSize, rPreviewModelSize, true, false);
    1093             : }
    1094             : 
    1095           0 : void VerticalImplementation::CalculateLogicalInsertPosition (
    1096             :     const Point& rModelPosition,
    1097             :     InsertPosition& rPosition) const
    1098             : {
    1099           0 :     return CalculateVerticalLogicalInsertPosition(rModelPosition, rPosition);
    1100             : }
    1101             : 
    1102             : //===== GridImplementation ================================================
    1103             : 
    1104          64 : GridImplementation::GridImplementation (
    1105             :     sd::Window *pWindow,
    1106             :     const ::boost::shared_ptr<view::Theme>& rpTheme)
    1107          64 :     : Implementation(pWindow, rpTheme)
    1108             : {
    1109          64 : }
    1110             : 
    1111          66 : GridImplementation::GridImplementation (const Implementation& rImplementation)
    1112          66 :     : Implementation(rImplementation)
    1113             : {
    1114          66 : }
    1115             : 
    1116         138 : Layouter::Orientation GridImplementation::GetOrientation() const
    1117             : {
    1118         138 :     return Layouter::GRID;
    1119             : }
    1120             : 
    1121         138 : void GridImplementation::CalculateRowAndColumnCount (const Size& rWindowSize)
    1122             : {
    1123             :     // Calculate the column count.
    1124             :     mnColumnCount
    1125         138 :         = (rWindowSize.Width() - mnRequestedLeftBorder - mnRequestedRightBorder)
    1126         138 :         / (maPreferredSize.Width()  + mnHorizontalGap);
    1127         138 :     if (mnColumnCount < mnMinimalColumnCount)
    1128         138 :         mnColumnCount = mnMinimalColumnCount;
    1129         138 :     if (mnColumnCount > mnMaximalColumnCount)
    1130           0 :         mnColumnCount = mnMaximalColumnCount;
    1131         138 :     mnRowCount = (mnPageCount + mnColumnCount-1)/mnColumnCount;
    1132         138 : }
    1133             : 
    1134         138 : void GridImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
    1135             : {
    1136         138 :     mnMaxColumnCount = (rWindowSize.Width() - mnLeftBorder - mnRightBorder)
    1137         138 :         / (maPageObjectSize.Width()  + mnHorizontalGap);
    1138         138 :     mnMaxRowCount = (rWindowSize.Height() - mnTopBorder - mnBottomBorder)
    1139         138 :         / (maPageObjectSize.Height()  + mnVerticalGap);
    1140         138 : }
    1141             : 
    1142         138 : Size GridImplementation::CalculateTargetSize (
    1143             :     const Size& rWindowSize,
    1144             :     const Size& rPreviewModelSize) const
    1145             : {
    1146         138 :     return Implementation::GetTargetSize(rWindowSize, rPreviewModelSize, true, true);
    1147             : }
    1148             : 
    1149           0 : void GridImplementation::CalculateLogicalInsertPosition (
    1150             :     const Point& rModelPosition,
    1151             :     InsertPosition& rPosition) const
    1152             : {
    1153           0 :     if (mnColumnCount == 1)
    1154             :     {
    1155           0 :         CalculateVerticalLogicalInsertPosition(rModelPosition, rPosition);
    1156             :     }
    1157             :     else
    1158             :     {
    1159             :         // Handle the general case of more than one column.
    1160             :         sal_Int32 nRow (::std::min(
    1161           0 :             mnRowCount-1,
    1162           0 :             GetRowAtPosition (rModelPosition.Y(), true, GM_BOTH)));
    1163           0 :         const sal_Int32 nX = rModelPosition.X() - mnLeftBorder + maPageObjectSize.Width()/2;
    1164           0 :         const sal_Int32 nColumnWidth (maPageObjectSize.Width() + mnHorizontalGap);
    1165           0 :         sal_Int32 nColumn (::std::min(mnColumnCount, nX / nColumnWidth));
    1166           0 :         sal_Int32 nIndex (nRow * mnColumnCount + nColumn);
    1167           0 :         bool bIsAtRunEnd (nColumn == mnColumnCount);
    1168             : 
    1169           0 :         if (nIndex >= mnPageCount)
    1170             :         {
    1171           0 :             nIndex = mnPageCount;
    1172           0 :             nRow = mnRowCount-1;
    1173           0 :             nColumn = ::std::min(::std::min(mnPageCount, mnColumnCount), nColumn);
    1174           0 :             bIsAtRunEnd = true;
    1175             :         }
    1176             : 
    1177             :         rPosition.SetLogicalPosition (
    1178             :             nRow,
    1179             :             nColumn,
    1180             :             nIndex,
    1181             :             (nColumn == 0),
    1182             :             bIsAtRunEnd,
    1183           0 :             (nColumn >= mnMaxColumnCount));
    1184             :     }
    1185           0 : }
    1186             : 
    1187             : //===== InsertPosition ========================================================
    1188             : 
    1189          64 : InsertPosition::InsertPosition()
    1190             :     : mnRow(-1),
    1191             :       mnColumn(-1),
    1192             :       mnIndex(-1),
    1193             :       mbIsAtRunStart(false),
    1194             :       mbIsAtRunEnd(false),
    1195             :       mbIsExtraSpaceNeeded(false),
    1196             :       maLocation(0,0),
    1197             :       maLeadingOffset(0,0),
    1198          64 :       maTrailingOffset(0,0)
    1199             : {
    1200          64 : }
    1201             : 
    1202           0 : InsertPosition& InsertPosition::operator= (const InsertPosition& rInsertPosition)
    1203             : {
    1204           0 :     if (this != &rInsertPosition)
    1205             :     {
    1206           0 :         mnRow = rInsertPosition.mnRow;
    1207           0 :         mnColumn = rInsertPosition.mnColumn;
    1208           0 :         mnIndex = rInsertPosition.mnIndex;
    1209           0 :         mbIsAtRunStart = rInsertPosition.mbIsAtRunStart;
    1210           0 :         mbIsAtRunEnd = rInsertPosition.mbIsAtRunEnd;
    1211           0 :         mbIsExtraSpaceNeeded = rInsertPosition.mbIsExtraSpaceNeeded;
    1212           0 :         maLocation = rInsertPosition.maLocation;
    1213           0 :         maLeadingOffset = rInsertPosition.maLeadingOffset;
    1214           0 :         maTrailingOffset = rInsertPosition.maTrailingOffset;
    1215             :     }
    1216           0 :     return *this;
    1217             : }
    1218             : 
    1219           0 : bool InsertPosition::operator== (const InsertPosition& rInsertPosition) const
    1220             : {
    1221             :     // Do not compare the geometrical information (maLocation).
    1222           0 :     return mnRow==rInsertPosition.mnRow
    1223           0 :         && mnColumn==rInsertPosition.mnColumn
    1224           0 :         && mnIndex==rInsertPosition.mnIndex
    1225           0 :         && mbIsAtRunStart==rInsertPosition.mbIsAtRunStart
    1226           0 :         && mbIsAtRunEnd==rInsertPosition.mbIsAtRunEnd
    1227           0 :         && mbIsExtraSpaceNeeded==rInsertPosition.mbIsExtraSpaceNeeded;
    1228             : }
    1229             : 
    1230           0 : bool InsertPosition::operator!= (const InsertPosition& rInsertPosition) const
    1231             : {
    1232           0 :     return !operator==(rInsertPosition);
    1233             : }
    1234             : 
    1235           0 : void InsertPosition::SetLogicalPosition (
    1236             :     const sal_Int32 nRow,
    1237             :     const sal_Int32 nColumn,
    1238             :     const sal_Int32 nIndex,
    1239             :     const bool bIsAtRunStart,
    1240             :     const bool bIsAtRunEnd,
    1241             :     const bool bIsExtraSpaceNeeded)
    1242             : {
    1243           0 :     mnRow = nRow;
    1244           0 :     mnColumn = nColumn;
    1245           0 :     mnIndex = nIndex;
    1246           0 :     mbIsAtRunStart = bIsAtRunStart;
    1247           0 :     mbIsAtRunEnd = bIsAtRunEnd;
    1248           0 :     mbIsExtraSpaceNeeded = bIsExtraSpaceNeeded;
    1249           0 : }
    1250             : 
    1251           0 : void InsertPosition::SetGeometricalPosition(
    1252             :     const Point& rLocation,
    1253             :     const Point& rLeadingOffset,
    1254             :     const Point& rTrailingOffset)
    1255             : {
    1256           0 :     maLocation = rLocation;
    1257           0 :     maLeadingOffset = rLeadingOffset;
    1258           0 :     maTrailingOffset = rTrailingOffset;
    1259           0 : }
    1260             : 
    1261             : } } } // end of namespace ::sd::slidesorter::namespace
    1262             : 
    1263             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11