1548 lines
42 KiB
C++
1548 lines
42 KiB
C++
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
#include "precompiled_sd.hxx"
|
|
|
|
#include "view/SlsLayouter.hxx"
|
|
#include "model/SlideSorterModel.hxx"
|
|
#include "model/SlsPageDescriptor.hxx"
|
|
#include "Window.hxx"
|
|
#include <rtl/math.hxx>
|
|
#include <basegfx/numeric/ftools.hxx>
|
|
|
|
namespace {
|
|
sal_Int32 RoundToInt (const double nValue)
|
|
{
|
|
return sal_Int32(::rtl::math::round(nValue));
|
|
}
|
|
}
|
|
|
|
|
|
namespace sd { namespace slidesorter { namespace view {
|
|
|
|
class Layouter::Implementation
|
|
{
|
|
public:
|
|
SharedSdWindow mpWindow;
|
|
sal_Int32 mnRequestedLeftBorder;
|
|
sal_Int32 mnRequestedRightBorder;
|
|
sal_Int32 mnRequestedTopBorder;
|
|
sal_Int32 mnRequestedBottomBorder;
|
|
sal_Int32 mnLeftBorder;
|
|
sal_Int32 mnRightBorder;
|
|
sal_Int32 mnTopBorder;
|
|
sal_Int32 mnBottomBorder;
|
|
sal_Int32 mnVerticalGap;
|
|
sal_Int32 mnHorizontalGap;
|
|
Size maMinimalSize;
|
|
Size maPreferredSize;
|
|
Size maMaximalSize;
|
|
sal_Int32 mnMinimalColumnCount;
|
|
sal_Int32 mnMaximalColumnCount;
|
|
sal_Int32 mnPageCount;
|
|
sal_Int32 mnColumnCount;
|
|
sal_Int32 mnRowCount;
|
|
/// The maximum number of columns. Can only be larger than the current
|
|
/// number of columns when there are not enough pages to fill all
|
|
/// available columns.
|
|
sal_Int32 mnMaxColumnCount;
|
|
/// The maximum number of rows. Can only be larger than the current
|
|
/// number of rows when there are not enough pages to fill all available
|
|
/// rows.
|
|
sal_Int32 mnMaxRowCount;
|
|
Size maPageObjectSize;
|
|
|
|
::boost::shared_ptr<PageObjectLayouter> mpPageObjectLayouter;
|
|
|
|
/** Specify how the gap between two page objects is associated with the
|
|
page objects.
|
|
*/
|
|
enum GapMembership {
|
|
GM_NONE, // Gap is not associated with any page object.
|
|
GM_PREVIOUS, // The whole gap is associated with the previous page
|
|
// object (left or above the gap.)
|
|
GM_BOTH, // Half of the gap is associated with previous, half
|
|
// with the next page object.
|
|
GM_NEXT, // The whole gap is associated with the next page
|
|
// object (right or below the gap.)
|
|
GM_PAGE_BORDER
|
|
};
|
|
|
|
static Implementation* Create (
|
|
const Implementation& rImplementation,
|
|
const Layouter::Orientation eOrientation);
|
|
|
|
virtual Layouter::Orientation GetOrientation (void) const = 0;
|
|
|
|
bool Rearrange (
|
|
const Size& rWindowSize,
|
|
const Size& rPreviewModelSize,
|
|
const sal_uInt32 nPageCount);
|
|
|
|
/** Calculate the row that the point with the given vertical coordinate
|
|
is over. The horizontal component is ignored.
|
|
@param nYPosition
|
|
Vertical position in model coordinates.
|
|
@param bIncludeBordersAndGaps
|
|
When this flag is <TRUE/> then the area of borders and gaps are
|
|
interpreted as belonging to one of the rows.
|
|
@param eGapMembership
|
|
Specifies to what row the gap areas belong. Here GM_NONE
|
|
corresponds to bIncludeBordersAndGaps being <FALSE/>. When
|
|
GM_BOTH is given then the upper half is associated to the row
|
|
above and the lower half to the row below. Values of
|
|
GM_PREVIOUS and GM_NEXT associate the whole gap area with the
|
|
row above or below respectively.
|
|
*/
|
|
sal_Int32 GetRowAtPosition (
|
|
sal_Int32 nYPosition,
|
|
bool bIncludeBordersAndGaps,
|
|
GapMembership eGapMembership = GM_NONE) const;
|
|
|
|
/** Calculate the column that the point with the given horizontal
|
|
coordinate is over. The verical component is ignored.
|
|
@param nXPosition
|
|
Horizontal position in model coordinates.
|
|
@param bIncludeBordersAndGaps
|
|
When this flag is <TRUE/> then the area of borders and gaps are
|
|
interpreted as belonging to one of the columns.
|
|
@param eGapMembership
|
|
Specifies to what column the gap areas belong.
|
|
*/
|
|
sal_Int32 GetColumnAtPosition (
|
|
sal_Int32 nXPosition,
|
|
bool bIncludeBordersAndGaps,
|
|
GapMembership eGapMembership = GM_NONE) const;
|
|
|
|
/** This method is typically called from GetRowAtPosition() and
|
|
GetColumnAtPosition() to handle a position that lies inside the gap
|
|
between two adjacent rows or columns.
|
|
@param nDistanceIntoGap
|
|
Vertical distance from the bottom of the upper row down into the
|
|
gap or or horizontal distance from the right edge right into the
|
|
gap.
|
|
@param eGapMemberhship
|
|
This value decides what areas in the gap belong to which (or no)
|
|
row or column.
|
|
@param nIndex
|
|
The row index of the upper row or the column index of the left
|
|
column.
|
|
@param nGap
|
|
Width or height of the gap in model coordiantes between the
|
|
page borders.
|
|
@return
|
|
Returns either the index of the upper row (as given as nRow), the
|
|
index of the lower row (nRow+1) or -1 to indicate that the
|
|
position belongs to no row.
|
|
*/
|
|
sal_Int32 ResolvePositionInGap (
|
|
sal_Int32 nDistanceIntoGap,
|
|
GapMembership eGapMembership,
|
|
sal_Int32 nIndex,
|
|
sal_Int32 nGap) const;
|
|
|
|
/** Calculate the logical part of the insert position, i.e. the page
|
|
after whicht to insert.
|
|
*/
|
|
virtual void CalculateLogicalInsertPosition (
|
|
const Point& rModelPosition,
|
|
InsertPosition& rPosition) const = 0;
|
|
|
|
/** Calculate the geometrical part of the insert position, i.e. the
|
|
location of where to display the insertion indicator and the
|
|
distances about which the leading and trailing pages have to be
|
|
moved to make room for the indicator.
|
|
*/
|
|
void CalculateGeometricPosition (
|
|
InsertPosition& rPosition,
|
|
const Size& rIndicatorSize,
|
|
const bool bIsVertical,
|
|
model::SlideSorterModel& rModel) const;
|
|
|
|
/** Return the bounding box of the preview or, when selected, of the page
|
|
object. Thus, it returns something like a visual bounding box.
|
|
*/
|
|
Rectangle GetInnerBoundingBox (
|
|
model::SlideSorterModel& rModel,
|
|
const sal_Int32 nIndex) const;
|
|
|
|
Range GetValidHorizontalSizeRange (void) const;
|
|
Range GetValidVerticalSizeRange (void) const;
|
|
|
|
Range GetRangeOfVisiblePageObjects (const Rectangle& aVisibleArea) const;
|
|
sal_Int32 GetIndex (
|
|
const sal_Int32 nRow,
|
|
const sal_Int32 nColumn,
|
|
const bool bClampToValidRange) const;
|
|
|
|
Rectangle GetPageObjectBox (
|
|
const sal_Int32 nIndex,
|
|
const bool bIncludeBorderAndGap = false) const;
|
|
|
|
Rectangle GetPageObjectBox (
|
|
const sal_Int32 nRow,
|
|
const sal_Int32 nColumn) const;
|
|
|
|
Rectangle AddBorderAndGap (
|
|
const Rectangle& rBoundingBox,
|
|
const sal_Int32 nRow,
|
|
const sal_Int32 nColumn) const;
|
|
|
|
Rectangle GetTotalBoundingBox (void) const;
|
|
|
|
virtual ~Implementation (void);
|
|
protected:
|
|
Implementation (const SharedSdWindow& rpWindow);
|
|
Implementation (const Implementation& rImplementation);
|
|
|
|
virtual void CalculateRowAndColumnCount (const Size& rWindowSize) = 0;
|
|
virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize) = 0;
|
|
virtual Size CalculateTargetSize (
|
|
const Size& rWindowSize,
|
|
const Size& rPreviewModelSize) const = 0;
|
|
Size GetTargetSize (
|
|
const Size& rWindowSize,
|
|
const Size& rPreviewModelSize,
|
|
const bool bCalculateWidth,
|
|
const bool bCalculateHeight) const;
|
|
void CalculateVerticalLogicalInsertPosition (
|
|
const Point& rModelPosition,
|
|
InsertPosition& rPosition) const;
|
|
};
|
|
|
|
|
|
/** The vertical layouter has one column and as many rows as there are
|
|
pages.
|
|
*/
|
|
class VerticalImplementation : public Layouter::Implementation
|
|
{
|
|
public:
|
|
VerticalImplementation (const SharedSdWindow& rpWindow);
|
|
VerticalImplementation (const Implementation& rImplementation);
|
|
|
|
virtual Layouter::Orientation GetOrientation (void) const;
|
|
|
|
void CalculateLogicalInsertPosition (
|
|
const Point& rModelPosition,
|
|
InsertPosition& rPosition) const;
|
|
|
|
protected:
|
|
virtual void CalculateRowAndColumnCount (const Size& rWindowSize);
|
|
virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize);
|
|
virtual Size CalculateTargetSize (
|
|
const Size& rWindowSize,
|
|
const Size& rPreviewModelSize) const;
|
|
};
|
|
|
|
|
|
/** The horizontal layouter has one row and as many columns as there are
|
|
pages.
|
|
*/
|
|
class HorizontalImplementation : public Layouter::Implementation
|
|
{
|
|
public:
|
|
HorizontalImplementation (const SharedSdWindow& rpWindow);
|
|
HorizontalImplementation (const Implementation& rImplementation);
|
|
|
|
virtual Layouter::Orientation GetOrientation (void) const;
|
|
|
|
void CalculateLogicalInsertPosition (
|
|
const Point& rModelPosition,
|
|
InsertPosition& rPosition) const;
|
|
|
|
protected:
|
|
virtual void CalculateRowAndColumnCount (const Size& rWindowSize);
|
|
virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize);
|
|
virtual Size CalculateTargetSize (
|
|
const Size& rWindowSize,
|
|
const Size& rPreviewModelSize) const;
|
|
};
|
|
|
|
|
|
/** The number of columns of the grid layouter is defined via a control in
|
|
the slide sorter tool bar. The number of rows is calculated from the
|
|
number of columns and the number of pages.
|
|
*/
|
|
class GridImplementation : public Layouter::Implementation
|
|
{
|
|
public:
|
|
GridImplementation (const SharedSdWindow& rpWindow);
|
|
GridImplementation (const Implementation& rImplementation);
|
|
|
|
virtual Layouter::Orientation GetOrientation (void) const;
|
|
|
|
void CalculateLogicalInsertPosition (
|
|
const Point& rModelPosition,
|
|
InsertPosition& rPosition) const;
|
|
|
|
protected:
|
|
virtual void CalculateRowAndColumnCount (const Size& rWindowSize);
|
|
virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize);
|
|
virtual Size CalculateTargetSize (
|
|
const Size& rWindowSize,
|
|
const Size& rPreviewModelSize) const;
|
|
};
|
|
|
|
|
|
|
|
|
|
//===== Layouter ==============================================================
|
|
|
|
Layouter::Layouter (const SharedSdWindow& rpWindow)
|
|
: mpImplementation(new GridImplementation(rpWindow)),
|
|
mpWindow(rpWindow)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
Layouter::~Layouter (void)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
::boost::shared_ptr<PageObjectLayouter> Layouter::GetPageObjectLayouter (void) const
|
|
{
|
|
return mpImplementation->mpPageObjectLayouter;
|
|
}
|
|
|
|
|
|
|
|
|
|
void Layouter::SetBorders (
|
|
sal_Int32 nLeftBorder,
|
|
sal_Int32 nRightBorder,
|
|
sal_Int32 nTopBorder,
|
|
sal_Int32 nBottomBorder)
|
|
{
|
|
if (nLeftBorder >= 0)
|
|
mpImplementation->mnRequestedLeftBorder = nLeftBorder;
|
|
if (nRightBorder >= 0)
|
|
mpImplementation->mnRequestedRightBorder = nRightBorder;
|
|
if (nTopBorder >= 0)
|
|
mpImplementation->mnRequestedTopBorder = nTopBorder;
|
|
if (nBottomBorder >= 0)
|
|
mpImplementation->mnRequestedBottomBorder = nBottomBorder;
|
|
}
|
|
|
|
|
|
|
|
|
|
void Layouter::SetGaps (
|
|
sal_Int32 nHorizontalGap,
|
|
sal_Int32 nVerticalGap)
|
|
{
|
|
if (nHorizontalGap >= 0)
|
|
mpImplementation->mnHorizontalGap = nHorizontalGap;
|
|
if (nVerticalGap >= 0)
|
|
mpImplementation->mnVerticalGap = nVerticalGap;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Layouter::SetColumnCount (
|
|
sal_Int32 nMinimalColumnCount,
|
|
sal_Int32 nMaximalColumnCount)
|
|
{
|
|
if (nMinimalColumnCount <= nMaximalColumnCount)
|
|
{
|
|
mpImplementation->mnMinimalColumnCount = nMinimalColumnCount;
|
|
mpImplementation->mnMaximalColumnCount = nMaximalColumnCount;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Layouter::Rearrange (
|
|
const Orientation eOrientation,
|
|
const Size& rWindowSize,
|
|
const Size& rPageSize,
|
|
const sal_uInt32 nPageCount)
|
|
{
|
|
OSL_ASSERT(mpWindow);
|
|
|
|
if (eOrientation != mpImplementation->GetOrientation())
|
|
mpImplementation.reset(Implementation::Create(*mpImplementation, eOrientation));
|
|
|
|
return mpImplementation->Rearrange(rWindowSize, rPageSize, nPageCount);
|
|
}
|
|
|
|
|
|
|
|
|
|
void Layouter::_SetZoom (double nZoomFactor)
|
|
{
|
|
_SetZoom(Fraction(nZoomFactor));
|
|
}
|
|
|
|
|
|
|
|
|
|
void Layouter::_SetZoom (Fraction nZoomFactor)
|
|
{
|
|
OSL_ASSERT(mpWindow);
|
|
|
|
MapMode aMapMode (mpWindow->GetMapMode());
|
|
aMapMode.SetScaleX (nZoomFactor);
|
|
aMapMode.SetScaleY (nZoomFactor);
|
|
mpWindow->SetMapMode (aMapMode);
|
|
}
|
|
|
|
|
|
|
|
|
|
sal_Int32 Layouter::GetColumnCount (void) const
|
|
{
|
|
return mpImplementation->mnColumnCount;
|
|
}
|
|
|
|
|
|
|
|
|
|
sal_Int32 Layouter::GetRowCount (void) const
|
|
{
|
|
return mpImplementation->mnRowCount;
|
|
}
|
|
|
|
|
|
|
|
|
|
sal_Int32 Layouter::GetRow (const sal_Int32 nIndex) const
|
|
{
|
|
return nIndex / mpImplementation->mnColumnCount;
|
|
}
|
|
|
|
|
|
|
|
|
|
sal_Int32 Layouter::GetColumn (const sal_Int32 nIndex) const
|
|
{
|
|
return nIndex % mpImplementation->mnColumnCount;
|
|
}
|
|
|
|
|
|
|
|
|
|
sal_Int32 Layouter::GetIndex (const sal_Int32 nRow, const sal_Int32 nColumn) const
|
|
{
|
|
return mpImplementation->GetIndex(nRow,nColumn,true);
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Layouter::IsColumnCountFixed (void) const
|
|
{
|
|
return mpImplementation->mnMinimalColumnCount == mpImplementation->mnMaximalColumnCount;
|
|
}
|
|
|
|
|
|
|
|
|
|
Size Layouter::GetPageObjectSize (void) const
|
|
{
|
|
return mpImplementation->maPageObjectSize;
|
|
}
|
|
|
|
|
|
|
|
|
|
Rectangle Layouter::GetPageObjectBox (
|
|
const sal_Int32 nIndex,
|
|
const bool bIncludeBorderAndGap) const
|
|
{
|
|
return mpImplementation->GetPageObjectBox(nIndex, bIncludeBorderAndGap);
|
|
}
|
|
|
|
|
|
|
|
|
|
Rectangle Layouter::GetTotalBoundingBox (void) const
|
|
{
|
|
return mpImplementation->GetTotalBoundingBox();
|
|
}
|
|
|
|
|
|
|
|
|
|
InsertPosition Layouter::GetInsertPosition (
|
|
const Point& rModelPosition,
|
|
const Size& rIndicatorSize,
|
|
model::SlideSorterModel& rModel) const
|
|
{
|
|
InsertPosition aPosition;
|
|
mpImplementation->CalculateLogicalInsertPosition(
|
|
rModelPosition,
|
|
aPosition);
|
|
mpImplementation->CalculateGeometricPosition(
|
|
aPosition,
|
|
rIndicatorSize,
|
|
GetColumnCount()==1,
|
|
rModel);
|
|
return aPosition;
|
|
}
|
|
|
|
|
|
|
|
|
|
Range Layouter::GetValidHorizontalSizeRange (void) const
|
|
{
|
|
return mpImplementation->GetValidHorizontalSizeRange();
|
|
}
|
|
|
|
|
|
|
|
|
|
Range Layouter::GetValidVerticalSizeRange (void) const
|
|
{
|
|
return mpImplementation->GetValidVerticalSizeRange();
|
|
}
|
|
|
|
|
|
|
|
|
|
Range Layouter::GetRangeOfVisiblePageObjects (const Rectangle& aVisibleArea) const
|
|
{
|
|
return mpImplementation->GetRangeOfVisiblePageObjects(aVisibleArea);
|
|
}
|
|
|
|
|
|
|
|
|
|
sal_Int32 Layouter::GetIndexAtPoint (
|
|
const Point& rPosition,
|
|
const bool bIncludePageBorders,
|
|
const bool bClampToValidRange) const
|
|
{
|
|
const sal_Int32 nRow (
|
|
mpImplementation->GetRowAtPosition (
|
|
rPosition.Y(),
|
|
bIncludePageBorders,
|
|
bIncludePageBorders ? Implementation::GM_PAGE_BORDER : Implementation::GM_NONE));
|
|
const sal_Int32 nColumn (
|
|
mpImplementation->GetColumnAtPosition (
|
|
rPosition.X(),
|
|
bIncludePageBorders,
|
|
bIncludePageBorders ? Implementation::GM_PAGE_BORDER : Implementation::GM_NONE));
|
|
|
|
return mpImplementation->GetIndex(nRow,nColumn,bClampToValidRange);
|
|
}
|
|
|
|
|
|
|
|
|
|
//===== Layouter::Implementation ==============================================
|
|
|
|
Layouter::Implementation* Layouter::Implementation::Create (
|
|
const Implementation& rImplementation,
|
|
const Layouter::Orientation eOrientation)
|
|
{
|
|
switch (eOrientation)
|
|
{
|
|
case HORIZONTAL: return new HorizontalImplementation(rImplementation);
|
|
case VERTICAL: return new VerticalImplementation(rImplementation);
|
|
case GRID:
|
|
default: return new GridImplementation(rImplementation);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
Layouter::Implementation::Implementation (const SharedSdWindow& rpWindow)
|
|
: mpWindow(rpWindow),
|
|
mnRequestedLeftBorder(5),
|
|
mnRequestedRightBorder(5),
|
|
mnRequestedTopBorder(5),
|
|
mnRequestedBottomBorder(5),
|
|
mnLeftBorder(5),
|
|
mnRightBorder(5),
|
|
mnTopBorder(5),
|
|
mnBottomBorder(5),
|
|
mnVerticalGap (10),
|
|
mnHorizontalGap(10),
|
|
maMinimalSize(100,75),
|
|
maPreferredSize(200,150),
|
|
maMaximalSize(300,200),
|
|
mnMinimalColumnCount(1),
|
|
mnMaximalColumnCount(15),
|
|
mnPageCount(0),
|
|
mnColumnCount(1),
|
|
mnRowCount(0),
|
|
mnMaxColumnCount(0),
|
|
mnMaxRowCount(0),
|
|
maPageObjectSize(1,1)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
Layouter::Implementation::Implementation (const Implementation& rImplementation)
|
|
: mpWindow(rImplementation.mpWindow),
|
|
mnRequestedLeftBorder(rImplementation.mnRequestedLeftBorder),
|
|
mnRequestedRightBorder(rImplementation.mnRequestedRightBorder),
|
|
mnRequestedTopBorder(rImplementation.mnRequestedTopBorder),
|
|
mnRequestedBottomBorder(rImplementation.mnRequestedBottomBorder),
|
|
mnLeftBorder(rImplementation.mnLeftBorder),
|
|
mnRightBorder(rImplementation.mnRightBorder),
|
|
mnTopBorder(rImplementation.mnTopBorder),
|
|
mnBottomBorder(rImplementation.mnBottomBorder),
|
|
mnVerticalGap(rImplementation.mnVerticalGap),
|
|
mnHorizontalGap(rImplementation.mnHorizontalGap),
|
|
maMinimalSize(rImplementation.maMinimalSize),
|
|
maPreferredSize(rImplementation.maPreferredSize),
|
|
maMaximalSize(rImplementation.maMaximalSize),
|
|
mnMinimalColumnCount(rImplementation.mnMinimalColumnCount),
|
|
mnMaximalColumnCount(rImplementation.mnMaximalColumnCount),
|
|
mnPageCount(rImplementation.mnPageCount),
|
|
mnColumnCount(rImplementation.mnColumnCount),
|
|
mnRowCount(rImplementation.mnRowCount),
|
|
mnMaxColumnCount(rImplementation.mnMaxColumnCount),
|
|
mnMaxRowCount(rImplementation.mnMaxRowCount),
|
|
maPageObjectSize(rImplementation.maPageObjectSize)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
Layouter::Implementation::~Implementation (void)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Layouter::Implementation::Rearrange (
|
|
const Size& rWindowSize,
|
|
const Size& rPreviewModelSize,
|
|
const sal_uInt32 nPageCount)
|
|
{
|
|
mnPageCount = nPageCount;
|
|
|
|
if (rWindowSize.Width()<=0 || rWindowSize.Height()<=0)
|
|
return false;
|
|
if (rPreviewModelSize.Width()<=0 || rPreviewModelSize.Height()<=0)
|
|
return false;
|
|
|
|
CalculateRowAndColumnCount(rWindowSize);
|
|
|
|
// Update the border values.
|
|
mnLeftBorder = mnRequestedLeftBorder;
|
|
mnTopBorder = mnRequestedTopBorder;
|
|
mnRightBorder = mnRequestedRightBorder;
|
|
mnBottomBorder = mnRequestedBottomBorder;
|
|
if (mnColumnCount > 1)
|
|
{
|
|
int nMinimumBorderWidth = mnHorizontalGap/2;
|
|
if (mnLeftBorder < nMinimumBorderWidth)
|
|
mnLeftBorder = nMinimumBorderWidth;
|
|
if (mnRightBorder < nMinimumBorderWidth)
|
|
mnRightBorder = nMinimumBorderWidth;
|
|
}
|
|
else
|
|
{
|
|
int nMinimumBorderHeight = mnVerticalGap/2;
|
|
if (mnTopBorder < nMinimumBorderHeight)
|
|
mnTopBorder = nMinimumBorderHeight;
|
|
if (mnBottomBorder < nMinimumBorderHeight)
|
|
mnBottomBorder = nMinimumBorderHeight;
|
|
}
|
|
|
|
mpPageObjectLayouter.reset(
|
|
new PageObjectLayouter(
|
|
CalculateTargetSize(rWindowSize, rPreviewModelSize),
|
|
rPreviewModelSize,
|
|
mpWindow,
|
|
mnPageCount));
|
|
maPageObjectSize = mpPageObjectLayouter->GetPageObjectSize();
|
|
|
|
CalculateMaxRowAndColumnCount(rWindowSize);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
sal_Int32 Layouter::Implementation::GetRowAtPosition (
|
|
sal_Int32 nYPosition,
|
|
bool bIncludeBordersAndGaps,
|
|
GapMembership eGapMembership) const
|
|
{
|
|
sal_Int32 nRow = -1;
|
|
|
|
const sal_Int32 nY = nYPosition - mnTopBorder;
|
|
if (nY >= 0)
|
|
{
|
|
// Vertical distance from one row to the next.
|
|
const sal_Int32 nRowOffset (maPageObjectSize.Height() + mnVerticalGap);
|
|
|
|
// Calculate row consisting of page objects and gap below.
|
|
nRow = nY / nRowOffset;
|
|
|
|
const sal_Int32 nDistanceIntoGap ((nY - nRow*nRowOffset) - maPageObjectSize.Height());
|
|
// When inside the gap below then nYPosition is not over a page
|
|
// object.
|
|
if (nDistanceIntoGap > 0)
|
|
nRow = ResolvePositionInGap (
|
|
nDistanceIntoGap,
|
|
eGapMembership,
|
|
nRow,
|
|
mnVerticalGap);
|
|
}
|
|
else if (bIncludeBordersAndGaps)
|
|
{
|
|
// We are in the top border area. Set nRow to the first row when
|
|
// the top border shall be considered to belong to the first row.
|
|
nRow = 0;
|
|
}
|
|
|
|
return nRow;
|
|
}
|
|
|
|
|
|
|
|
|
|
sal_Int32 Layouter::Implementation::GetColumnAtPosition (
|
|
sal_Int32 nXPosition,
|
|
bool bIncludeBordersAndGaps,
|
|
GapMembership eGapMembership) const
|
|
{
|
|
sal_Int32 nColumn = -1;
|
|
|
|
sal_Int32 nX = nXPosition - mnLeftBorder;
|
|
if (nX >= 0)
|
|
{
|
|
// Horizontal distance from one column to the next.
|
|
const sal_Int32 nColumnOffset (maPageObjectSize.Width() + mnHorizontalGap);
|
|
|
|
// Calculate row consisting of page objects and gap below.
|
|
nColumn = nX / nColumnOffset;
|
|
if (nColumn < 0)
|
|
nColumn = 0;
|
|
else if (nColumn >= mnColumnCount)
|
|
nColumn = mnColumnCount-1;
|
|
|
|
const sal_Int32 nDistanceIntoGap ((nX - nColumn*nColumnOffset) - maPageObjectSize.Width());
|
|
// When inside the gap at the right then nXPosition is not over a
|
|
// page object.
|
|
if (nDistanceIntoGap > 0)
|
|
nColumn = ResolvePositionInGap (
|
|
nDistanceIntoGap,
|
|
eGapMembership,
|
|
nColumn,
|
|
mnHorizontalGap);
|
|
}
|
|
else if (bIncludeBordersAndGaps)
|
|
{
|
|
// We are in the left border area. Set nColumn to the first column
|
|
// when the left border shall be considered to belong to the first
|
|
// column.
|
|
nColumn = 0;
|
|
}
|
|
return nColumn;
|
|
}
|
|
|
|
|
|
|
|
|
|
sal_Int32 Layouter::Implementation::ResolvePositionInGap (
|
|
sal_Int32 nDistanceIntoGap,
|
|
GapMembership eGapMembership,
|
|
sal_Int32 nIndex,
|
|
sal_Int32 nGap) const
|
|
{
|
|
switch (eGapMembership)
|
|
{
|
|
case GM_NONE:
|
|
// The gap is no man's land.
|
|
nIndex = -1;
|
|
break;
|
|
|
|
case GM_BOTH:
|
|
{
|
|
// The lower half of the gap belongs to the next row or column.
|
|
sal_Int32 nFirstHalfGapWidth = nGap / 2;
|
|
if (nDistanceIntoGap > nFirstHalfGapWidth)
|
|
nIndex ++;
|
|
break;
|
|
}
|
|
|
|
case GM_PREVIOUS:
|
|
// Row or column already at correct value.
|
|
break;
|
|
|
|
case GM_NEXT:
|
|
// The complete gap belongs to the next row or column.
|
|
nIndex ++;
|
|
break;
|
|
|
|
case GM_PAGE_BORDER:
|
|
if (nDistanceIntoGap > 0)
|
|
{
|
|
if (nDistanceIntoGap > nGap)
|
|
{
|
|
// Inside the border of the next row or column.
|
|
nIndex ++;
|
|
}
|
|
else
|
|
{
|
|
// Inside the gap between the page borders.
|
|
nIndex = -1;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
nIndex = -1;
|
|
}
|
|
|
|
return nIndex;
|
|
}
|
|
|
|
|
|
|
|
|
|
void Layouter::Implementation::CalculateGeometricPosition (
|
|
InsertPosition& rPosition,
|
|
const Size& rIndicatorSize,
|
|
const bool bIsVertical,
|
|
model::SlideSorterModel& rModel) const
|
|
{
|
|
// 1. Determine right/bottom of the leading page and the left/top of the
|
|
// trailing page object and how to distribute the missing space.
|
|
sal_Int32 nLeadingLocation (0);
|
|
sal_Int32 nTrailingLocation (0);
|
|
bool bIsLeadingFixed (false);
|
|
bool bIsTrailingFixed (false);
|
|
sal_Int32 nSecondaryLocation (0);
|
|
const sal_Int32 nIndex (rPosition.GetIndex());
|
|
|
|
if (rPosition.IsAtRunStart())
|
|
{
|
|
// Place indicator at the top of the column.
|
|
const Rectangle aOuterBox (GetPageObjectBox(nIndex));
|
|
const Rectangle aInnerBox (GetInnerBoundingBox(rModel, nIndex));
|
|
if (bIsVertical)
|
|
{
|
|
nLeadingLocation = aOuterBox.Top();
|
|
nTrailingLocation = aInnerBox.Top();
|
|
nSecondaryLocation = aInnerBox.Center().X();
|
|
}
|
|
else
|
|
{
|
|
nLeadingLocation = aOuterBox.Left();
|
|
nTrailingLocation = aInnerBox.Left();
|
|
nSecondaryLocation = aInnerBox.Center().Y();
|
|
}
|
|
bIsLeadingFixed = true;
|
|
}
|
|
else if (rPosition.IsAtRunEnd())
|
|
{
|
|
// Place indicator at the bottom/right of the column/row.
|
|
|
|
const Rectangle aOuterBox (GetPageObjectBox(nIndex-1));
|
|
const Rectangle aInnerBox (GetInnerBoundingBox(rModel, nIndex-1));
|
|
if (bIsVertical)
|
|
{
|
|
nLeadingLocation = aInnerBox.Bottom();
|
|
nTrailingLocation = aOuterBox.Bottom();
|
|
nSecondaryLocation = aInnerBox.Center().X();
|
|
}
|
|
else
|
|
{
|
|
nLeadingLocation = aInnerBox.Right();
|
|
nTrailingLocation = aOuterBox.Right();
|
|
nSecondaryLocation = aInnerBox.Center().Y();
|
|
}
|
|
bIsTrailingFixed = true;
|
|
if ( ! rPosition.IsExtraSpaceNeeded())
|
|
bIsLeadingFixed = true;
|
|
}
|
|
else
|
|
{
|
|
// Place indicator between two rows/columns.
|
|
const Rectangle aBox1 (GetInnerBoundingBox(rModel, nIndex-1));
|
|
const Rectangle aBox2 (GetInnerBoundingBox(rModel, nIndex));
|
|
if (bIsVertical)
|
|
{
|
|
nLeadingLocation = aBox1.Bottom();
|
|
nTrailingLocation = aBox2.Top();
|
|
nSecondaryLocation = (aBox1.Center().X() + aBox2.Center().X()) / 2;
|
|
}
|
|
else
|
|
{
|
|
nLeadingLocation = aBox1.Right();
|
|
nTrailingLocation = aBox2.Left();
|
|
nSecondaryLocation = (aBox1.Center().Y() + aBox2.Center().Y()) / 2;
|
|
}
|
|
}
|
|
|
|
// 2. Calculate the location of the insert indicator and the offsets of
|
|
// leading and trailing pages.
|
|
const sal_Int32 nAvailableSpace (nTrailingLocation - nLeadingLocation);
|
|
const sal_Int32 nRequiredSpace (bIsVertical ? rIndicatorSize.Height():rIndicatorSize.Width());
|
|
const sal_Int32 nMissingSpace (::std::max(sal_Int32(0), nRequiredSpace - nAvailableSpace));
|
|
sal_Int32 nPrimaryLocation (0);
|
|
sal_Int32 nLeadingOffset (0);
|
|
sal_Int32 nTrailingOffset (0);
|
|
if (bIsLeadingFixed)
|
|
{
|
|
nPrimaryLocation = nLeadingLocation + nRequiredSpace/2;
|
|
if ( ! bIsTrailingFixed)
|
|
nTrailingOffset = nMissingSpace;
|
|
}
|
|
else if (bIsTrailingFixed)
|
|
{
|
|
nPrimaryLocation = nTrailingLocation - nRequiredSpace/2;
|
|
nLeadingOffset = -nMissingSpace;
|
|
}
|
|
else
|
|
{
|
|
nPrimaryLocation = (nLeadingLocation + nTrailingLocation) /2;
|
|
nLeadingOffset = -nMissingSpace/2;
|
|
nTrailingOffset = nMissingSpace + nLeadingOffset;
|
|
}
|
|
|
|
if (bIsVertical)
|
|
{
|
|
rPosition.SetGeometricalPosition(
|
|
Point(nSecondaryLocation, nPrimaryLocation),
|
|
Point(0, nLeadingOffset),
|
|
Point(0, nTrailingOffset));
|
|
}
|
|
else
|
|
{
|
|
rPosition.SetGeometricalPosition(
|
|
Point(nPrimaryLocation, nSecondaryLocation),
|
|
Point(nLeadingOffset, 0),
|
|
Point(nTrailingOffset, 0));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
Rectangle Layouter::Implementation::GetInnerBoundingBox (
|
|
model::SlideSorterModel& rModel,
|
|
const sal_Int32 nIndex) const
|
|
{
|
|
model::SharedPageDescriptor pDescriptor (rModel.GetPageDescriptor(nIndex));
|
|
if ( ! pDescriptor)
|
|
return Rectangle();
|
|
|
|
const Point aLocation (pDescriptor->GetLocation(true));
|
|
if (pDescriptor->HasState(model::PageDescriptor::ST_Selected))
|
|
return mpPageObjectLayouter->GetBoundingBox(
|
|
aLocation,
|
|
PageObjectLayouter::PageObject,
|
|
PageObjectLayouter::ModelCoordinateSystem);
|
|
else
|
|
return mpPageObjectLayouter->GetBoundingBox(
|
|
aLocation,
|
|
PageObjectLayouter::Preview,
|
|
PageObjectLayouter::ModelCoordinateSystem);
|
|
}
|
|
|
|
|
|
|
|
|
|
Range Layouter::Implementation::GetValidHorizontalSizeRange (void) const
|
|
{
|
|
return Range(
|
|
mnLeftBorder + maMinimalSize.Width() + mnRightBorder,
|
|
mnLeftBorder + maMaximalSize.Width() + mnRightBorder);
|
|
}
|
|
|
|
|
|
|
|
|
|
Range Layouter::Implementation::GetValidVerticalSizeRange (void) const
|
|
{
|
|
return Range(
|
|
mnTopBorder + maMinimalSize.Height() + mnBottomBorder,
|
|
mnTopBorder + maMaximalSize.Height() + mnBottomBorder);
|
|
}
|
|
|
|
|
|
|
|
|
|
Range Layouter::Implementation::GetRangeOfVisiblePageObjects (const Rectangle& aVisibleArea) const
|
|
{
|
|
const sal_Int32 nRow0 (GetRowAtPosition(aVisibleArea.Top(), true, GM_NEXT));
|
|
const sal_Int32 nCol0 (GetColumnAtPosition(aVisibleArea.Left(),true, GM_NEXT));
|
|
const sal_Int32 nRow1 (GetRowAtPosition(aVisibleArea.Bottom(), true, GM_PREVIOUS));
|
|
const sal_Int32 nCol1 (GetColumnAtPosition(aVisibleArea.Right(), true, GM_PREVIOUS));
|
|
|
|
// When start and end lie in different rows then the range may include
|
|
// slides outside (left or right of) the given area.
|
|
return Range(GetIndex(nRow0,nCol0,true), GetIndex(nRow1,nCol1,true));
|
|
}
|
|
|
|
|
|
|
|
|
|
Size Layouter::Implementation::GetTargetSize (
|
|
const Size& rWindowSize,
|
|
const Size& rPreviewModelSize,
|
|
const bool bCalculateWidth,
|
|
const bool bCalculateHeight) const
|
|
{
|
|
(void)rPreviewModelSize;
|
|
|
|
if (mnColumnCount<=0 || mnRowCount<=0)
|
|
return maPreferredSize;
|
|
if ( ! (bCalculateWidth || bCalculateHeight))
|
|
{
|
|
OSL_ASSERT(bCalculateWidth || bCalculateHeight);
|
|
return maPreferredSize;
|
|
}
|
|
|
|
// Calculate the width of each page object.
|
|
Size aTargetSize (0,0);
|
|
if (bCalculateWidth)
|
|
aTargetSize.setWidth(
|
|
(rWindowSize.Width() - mnLeftBorder - mnRightBorder
|
|
- (mnColumnCount-1) * mnHorizontalGap)
|
|
/ mnColumnCount);
|
|
else if (bCalculateHeight)
|
|
aTargetSize.setHeight(
|
|
(rWindowSize.Height() - mnTopBorder - mnBottomBorder
|
|
- (mnRowCount-1) * mnVerticalGap)
|
|
/ mnRowCount);
|
|
|
|
if (bCalculateWidth)
|
|
{
|
|
if (aTargetSize.Width() < maMinimalSize.Width())
|
|
aTargetSize.setWidth(maMinimalSize.Width());
|
|
else if (aTargetSize.Width() > maMaximalSize.Width())
|
|
aTargetSize.setWidth(maMaximalSize.Width());
|
|
}
|
|
else if (bCalculateHeight)
|
|
{
|
|
if (aTargetSize.Height() < maMinimalSize.Height())
|
|
aTargetSize.setHeight(maMinimalSize.Height());
|
|
else if (aTargetSize.Height() > maMaximalSize.Height())
|
|
aTargetSize.setHeight(maMaximalSize.Height());
|
|
}
|
|
|
|
return aTargetSize;
|
|
}
|
|
|
|
|
|
|
|
|
|
sal_Int32 Layouter::Implementation::GetIndex (
|
|
const sal_Int32 nRow,
|
|
const sal_Int32 nColumn,
|
|
const bool bClampToValidRange) const
|
|
{
|
|
if (nRow >= 0 && nColumn >= 0)
|
|
{
|
|
const sal_Int32 nIndex (nRow * mnColumnCount + nColumn);
|
|
if (nIndex >= mnPageCount)
|
|
if (bClampToValidRange)
|
|
return mnPageCount-1;
|
|
else
|
|
return -1;
|
|
else
|
|
return nIndex;
|
|
}
|
|
else if (bClampToValidRange)
|
|
return 0;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
|
|
Rectangle Layouter::Implementation::GetPageObjectBox (
|
|
const sal_Int32 nIndex,
|
|
const bool bIncludeBorderAndGap) const
|
|
{
|
|
const sal_Int32 nRow (nIndex / mnColumnCount);
|
|
const sal_Int32 nColumn (nIndex % mnColumnCount);
|
|
|
|
const Rectangle aBoundingBox (GetPageObjectBox(nRow,nColumn));
|
|
if (bIncludeBorderAndGap)
|
|
return AddBorderAndGap(aBoundingBox, nRow, nColumn);
|
|
else
|
|
return aBoundingBox;
|
|
}
|
|
|
|
|
|
|
|
|
|
Rectangle Layouter::Implementation::GetPageObjectBox (
|
|
const sal_Int32 nRow,
|
|
const sal_Int32 nColumn) const
|
|
{
|
|
return Rectangle(
|
|
Point (mnLeftBorder
|
|
+ nColumn * maPageObjectSize.Width()
|
|
+ (nColumn>0 ? nColumn : 0) * mnHorizontalGap,
|
|
mnTopBorder
|
|
+ nRow * maPageObjectSize.Height()
|
|
+ (nRow>0 ? nRow : 0) * mnVerticalGap),
|
|
maPageObjectSize);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rectangle Layouter::Implementation::AddBorderAndGap (
|
|
const Rectangle& rBoundingBox,
|
|
const sal_Int32 nRow,
|
|
const sal_Int32 nColumn) const
|
|
{
|
|
Rectangle aBoundingBox (rBoundingBox);
|
|
|
|
if (nColumn == 0)
|
|
aBoundingBox.Left() = 0;
|
|
else
|
|
aBoundingBox.Left() -= mnHorizontalGap/2;
|
|
if (nColumn == mnColumnCount-1)
|
|
aBoundingBox.Right() += mnRightBorder;
|
|
else
|
|
aBoundingBox.Right() += mnHorizontalGap/2;
|
|
if (nRow == 0)
|
|
aBoundingBox.Top() = 0;
|
|
else
|
|
aBoundingBox.Top() -= mnVerticalGap/2;
|
|
if (nRow == mnRowCount-1)
|
|
aBoundingBox.Bottom() += mnBottomBorder;
|
|
else
|
|
aBoundingBox.Bottom() += mnVerticalGap/2;
|
|
return aBoundingBox;
|
|
}
|
|
|
|
|
|
|
|
|
|
Rectangle Layouter::Implementation::GetTotalBoundingBox (void) const
|
|
{
|
|
sal_Int32 nHorizontalSize = 0;
|
|
sal_Int32 nVerticalSize = 0;
|
|
if (mnColumnCount > 0)
|
|
{
|
|
sal_Int32 nRowCount = (mnPageCount+mnColumnCount-1) / mnColumnCount;
|
|
nHorizontalSize =
|
|
mnLeftBorder
|
|
+ mnRightBorder
|
|
+ mnColumnCount * maPageObjectSize.Width();
|
|
if (mnColumnCount > 1)
|
|
nHorizontalSize += (mnColumnCount-1) * mnHorizontalGap;
|
|
nVerticalSize =
|
|
mnTopBorder
|
|
+ mnBottomBorder
|
|
+ nRowCount * maPageObjectSize.Height();
|
|
if (nRowCount > 1)
|
|
nVerticalSize += (nRowCount-1) * mnVerticalGap;
|
|
}
|
|
|
|
return Rectangle (
|
|
Point(0,0),
|
|
Size (nHorizontalSize, nVerticalSize)
|
|
);
|
|
}
|
|
|
|
|
|
|
|
|
|
void Layouter::Implementation::CalculateVerticalLogicalInsertPosition (
|
|
const Point& rModelPosition,
|
|
InsertPosition& rPosition) const
|
|
{
|
|
const sal_Int32 nY = rModelPosition.Y() - mnTopBorder + maPageObjectSize.Height()/2;
|
|
const sal_Int32 nRowHeight (maPageObjectSize.Height() + mnVerticalGap);
|
|
const sal_Int32 nRow (::std::min(mnPageCount, nY / nRowHeight));
|
|
rPosition.SetLogicalPosition (
|
|
nRow,
|
|
0,
|
|
nRow,
|
|
(nRow == 0),
|
|
(nRow == mnRowCount),
|
|
(nRow >= mnMaxRowCount));
|
|
}
|
|
|
|
|
|
|
|
|
|
//===== HorizontalImplementation ================================================
|
|
|
|
HorizontalImplementation::HorizontalImplementation (const SharedSdWindow& rpWindow)
|
|
: Implementation(rpWindow)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
HorizontalImplementation::HorizontalImplementation (const Implementation& rImplementation)
|
|
: Implementation(rImplementation)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
Layouter::Orientation HorizontalImplementation::GetOrientation (void) const
|
|
{
|
|
return Layouter::HORIZONTAL;
|
|
}
|
|
|
|
|
|
|
|
|
|
void HorizontalImplementation::CalculateRowAndColumnCount (const Size& rWindowSize)
|
|
{
|
|
(void)rWindowSize;
|
|
|
|
// Row and column count are fixed (for a given page count.)
|
|
mnColumnCount = mnPageCount;
|
|
mnRowCount = 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
void HorizontalImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
|
|
{
|
|
mnMaxColumnCount = (rWindowSize.Width() - mnLeftBorder - mnRightBorder)
|
|
/ (maPageObjectSize.Width() + mnHorizontalGap);
|
|
mnMaxRowCount = 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
Size HorizontalImplementation::CalculateTargetSize (
|
|
const Size& rWindowSize,
|
|
const Size& rPreviewModelSize) const
|
|
{
|
|
return Implementation::GetTargetSize(rWindowSize, rPreviewModelSize, false, true);
|
|
}
|
|
|
|
|
|
|
|
|
|
void HorizontalImplementation::CalculateLogicalInsertPosition (
|
|
const Point& rModelPosition,
|
|
InsertPosition& rPosition) const
|
|
{
|
|
const sal_Int32 nX = rModelPosition.X() - mnLeftBorder + maPageObjectSize.Width()/2;
|
|
const sal_Int32 nColumnWidth (maPageObjectSize.Width() + mnHorizontalGap);
|
|
const sal_Int32 nColumn (::std::min(mnPageCount, nX / nColumnWidth));
|
|
rPosition.SetLogicalPosition (
|
|
0,
|
|
nColumn,
|
|
nColumn,
|
|
(nColumn == 0),
|
|
(nColumn == mnColumnCount),
|
|
(nColumn >= mnMaxColumnCount));
|
|
}
|
|
|
|
|
|
|
|
|
|
//===== VerticalImplementation ================================================
|
|
|
|
VerticalImplementation::VerticalImplementation (const SharedSdWindow& rpWindow)
|
|
: Implementation(rpWindow)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
VerticalImplementation::VerticalImplementation (const Implementation& rImplementation)
|
|
: Implementation(rImplementation)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
Layouter::Orientation VerticalImplementation::GetOrientation (void) const
|
|
{
|
|
return Layouter::VERTICAL;
|
|
}
|
|
|
|
|
|
|
|
|
|
void VerticalImplementation::CalculateRowAndColumnCount (const Size& rWindowSize)
|
|
{
|
|
(void)rWindowSize;
|
|
|
|
// Row and column count are fixed (for a given page count.)
|
|
mnRowCount = mnPageCount;
|
|
mnColumnCount = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VerticalImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
|
|
{
|
|
mnMaxRowCount = (rWindowSize.Height() - mnTopBorder - mnBottomBorder)
|
|
/ (maPageObjectSize.Height() + mnVerticalGap);
|
|
mnMaxColumnCount = 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
Size VerticalImplementation::CalculateTargetSize (
|
|
const Size& rWindowSize,
|
|
const Size& rPreviewModelSize) const
|
|
{
|
|
return Implementation::GetTargetSize(rWindowSize, rPreviewModelSize, true, false);
|
|
}
|
|
|
|
|
|
|
|
|
|
void VerticalImplementation::CalculateLogicalInsertPosition (
|
|
const Point& rModelPosition,
|
|
InsertPosition& rPosition) const
|
|
{
|
|
return CalculateVerticalLogicalInsertPosition(rModelPosition, rPosition);
|
|
}
|
|
|
|
|
|
|
|
|
|
//===== GridImplementation ================================================
|
|
|
|
GridImplementation::GridImplementation (const SharedSdWindow& rpWindow)
|
|
: Implementation(rpWindow)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
GridImplementation::GridImplementation (const Implementation& rImplementation)
|
|
: Implementation(rImplementation)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
Layouter::Orientation GridImplementation::GetOrientation (void) const
|
|
{
|
|
return Layouter::GRID;
|
|
}
|
|
|
|
|
|
|
|
|
|
void GridImplementation::CalculateRowAndColumnCount (const Size& rWindowSize)
|
|
{
|
|
// Calculate the column count.
|
|
mnColumnCount
|
|
= (rWindowSize.Width() - mnRequestedLeftBorder - mnRequestedRightBorder)
|
|
/ (maPreferredSize.Width() + mnHorizontalGap);
|
|
if (mnColumnCount < mnMinimalColumnCount)
|
|
mnColumnCount = mnMinimalColumnCount;
|
|
if (mnColumnCount > mnMaximalColumnCount)
|
|
mnColumnCount = mnMaximalColumnCount;
|
|
mnRowCount = (mnPageCount + mnColumnCount-1)/mnColumnCount;
|
|
}
|
|
|
|
|
|
|
|
|
|
void GridImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
|
|
{
|
|
mnMaxColumnCount = (rWindowSize.Width() - mnLeftBorder - mnRightBorder)
|
|
/ (maPageObjectSize.Width() + mnHorizontalGap);
|
|
mnMaxRowCount = (rWindowSize.Height() - mnTopBorder - mnBottomBorder)
|
|
/ (maPageObjectSize.Height() + mnVerticalGap);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Size GridImplementation::CalculateTargetSize (
|
|
const Size& rWindowSize,
|
|
const Size& rPreviewModelSize) const
|
|
{
|
|
return Implementation::GetTargetSize(rWindowSize, rPreviewModelSize, true, true);
|
|
}
|
|
|
|
|
|
|
|
|
|
void GridImplementation::CalculateLogicalInsertPosition (
|
|
const Point& rModelPosition,
|
|
InsertPosition& rPosition) const
|
|
{
|
|
if (mnColumnCount == 1)
|
|
{
|
|
CalculateVerticalLogicalInsertPosition(rModelPosition, rPosition);
|
|
}
|
|
else
|
|
{
|
|
// Handle the general case of more than one column.
|
|
sal_Int32 nRow (::std::min(
|
|
mnRowCount-1,
|
|
GetRowAtPosition (rModelPosition.Y(), true, GM_BOTH)));
|
|
const sal_Int32 nX = rModelPosition.X() - mnLeftBorder + maPageObjectSize.Width()/2;
|
|
const sal_Int32 nColumnWidth (maPageObjectSize.Width() + mnHorizontalGap);
|
|
sal_Int32 nColumn (::std::min(mnColumnCount, nX / nColumnWidth));
|
|
sal_Int32 nIndex (nRow * mnColumnCount + nColumn);
|
|
bool bIsAtRunEnd (nColumn == mnColumnCount);
|
|
|
|
if (nIndex >= mnPageCount)
|
|
{
|
|
nIndex = mnPageCount;
|
|
nRow = mnRowCount-1;
|
|
nColumn = mnPageCount%mnColumnCount;
|
|
bIsAtRunEnd = true;
|
|
}
|
|
|
|
rPosition.SetLogicalPosition (
|
|
nRow,
|
|
nColumn,
|
|
nIndex,
|
|
(nColumn == 0),
|
|
bIsAtRunEnd,
|
|
(nColumn >= mnMaxColumnCount));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//===== InsertPosition ========================================================
|
|
|
|
InsertPosition::InsertPosition (void)
|
|
: mnRow(-1),
|
|
mnColumn(-1),
|
|
mnIndex(-1),
|
|
mbIsAtRunStart(false),
|
|
mbIsAtRunEnd(false),
|
|
mbIsExtraSpaceNeeded(false),
|
|
maLocation(0,0),
|
|
maLeadingOffset(0,0),
|
|
maTrailingOffset(0,0)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
InsertPosition& InsertPosition::operator= (const InsertPosition& rInsertPosition)
|
|
{
|
|
if (this != &rInsertPosition)
|
|
{
|
|
mnRow = rInsertPosition.mnRow;
|
|
mnColumn = rInsertPosition.mnColumn;
|
|
mnIndex = rInsertPosition.mnIndex;
|
|
mbIsAtRunStart = rInsertPosition.mbIsAtRunStart;
|
|
mbIsAtRunEnd = rInsertPosition.mbIsAtRunEnd;
|
|
mbIsExtraSpaceNeeded = rInsertPosition.mbIsExtraSpaceNeeded;
|
|
maLocation = rInsertPosition.maLocation;
|
|
maLeadingOffset = rInsertPosition.maLeadingOffset;
|
|
maTrailingOffset = rInsertPosition.maTrailingOffset;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
|
|
|
|
bool InsertPosition::operator== (const InsertPosition& rInsertPosition) const
|
|
{
|
|
// Do not compare the geometrical information (maLocation).
|
|
return mnRow==rInsertPosition.mnRow
|
|
&& mnColumn==rInsertPosition.mnColumn
|
|
&& mnIndex==rInsertPosition.mnIndex
|
|
&& mbIsAtRunStart==rInsertPosition.mbIsAtRunStart
|
|
&& mbIsAtRunEnd==rInsertPosition.mbIsAtRunEnd
|
|
&& mbIsExtraSpaceNeeded==rInsertPosition.mbIsExtraSpaceNeeded;
|
|
}
|
|
|
|
|
|
|
|
|
|
bool InsertPosition::operator!= (const InsertPosition& rInsertPosition) const
|
|
{
|
|
return !operator==(rInsertPosition);
|
|
}
|
|
|
|
|
|
|
|
|
|
void InsertPosition::SetLogicalPosition (
|
|
const sal_Int32 nRow,
|
|
const sal_Int32 nColumn,
|
|
const sal_Int32 nIndex,
|
|
const bool bIsAtRunStart,
|
|
const bool bIsAtRunEnd,
|
|
const bool bIsExtraSpaceNeeded)
|
|
{
|
|
mnRow = nRow;
|
|
mnColumn = nColumn;
|
|
mnIndex = nIndex;
|
|
mbIsAtRunStart = bIsAtRunStart;
|
|
mbIsAtRunEnd = bIsAtRunEnd;
|
|
mbIsExtraSpaceNeeded = bIsExtraSpaceNeeded;
|
|
}
|
|
|
|
|
|
|
|
|
|
void InsertPosition::SetGeometricalPosition(
|
|
const Point aLocation,
|
|
const Point aLeadingOffset,
|
|
const Point aTrailingOffset)
|
|
{
|
|
maLocation = aLocation;
|
|
maLeadingOffset = aLeadingOffset;
|
|
maTrailingOffset = aTrailingOffset;
|
|
}
|
|
|
|
|
|
|
|
} } } // end of namespace ::sd::slidesorter::namespace
|