office-gobmx/sd/source/ui/slidesorter/view/SlsLayouter.cxx
Release Engineers 3868442ba9 CWS-TOOLING: integrate CWS impress170
2009-04-28 10:31:12 +0200 wg  r271308 : i101397
2009-04-14 17:56:43 +0200 af  r270805 : #i100829# Removed line that became obsolete in last change.
2009-04-14 15:12:19 +0200 af  r270782 : #i97199# Made accelerators in text attribute dialog unique.
2009-04-14 14:42:53 +0200 af  r270775 : #i98364# Create regular task pane master previews even in high contrast mode.
2009-04-09 14:43:32 +0200 af  r270708 : #i92792# Show icon instead of text and register resource for 'Table Design'.
2009-04-09 14:42:51 +0200 af  r270707 : #i92792# Show icon instead of text and register resource for 'Table Design'.
2009-04-09 11:15:32 +0200 af  r270683 : #i85921# Applied patch that adds direct activation of master mode to task pane context menu.
2009-04-08 15:12:54 +0200 af  r270654 : #i94775# Passing snap line index from context menu to FuSnapLine.
2009-04-06 15:33:04 +0200 af  r270555 : #i95371# Return early from MoveToTop() when the dispatcher is (not yet) available.
2009-04-06 13:15:42 +0200 af  r270538 : #i97571# Fixed forwarding MouseButtonUp() calls to parent.
2009-04-03 16:10:08 +0200 af  r270498 : #i100830# Adjusted the sizes of some rectangles displayed by the slide sorter.
2009-04-03 16:02:08 +0200 af  r270496 : #i93086# Storing position of insertion indicator explicitly at SelectionManager.
2009-04-03 15:55:59 +0200 af  r270493 : #i100829# Calling UpdatePageBorders() when the model is changed.
2009-05-07 12:38:03 +00:00

816 lines
24 KiB
C++

/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2008 by Sun Microsystems, Inc.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: SlsLayouter.cxx,v $
* $Revision: 1.11 $
*
* 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 <vcl/outdev.hxx>
#include <rtl/math.hxx>
namespace sd { namespace slidesorter { namespace view {
Layouter::Layouter (void)
: mnRequestedLeftBorder(10),
mnRequestedRightBorder(10),
mnRequestedTopBorder(10),
mnRequestedBottomBorder(10),
mnLeftBorder(10),
mnRightBorder(10),
mnTopBorder(10),
mnBottomBorder(10),
mnLeftPageBorder(0),
mnRightPageBorder(0),
mnTopPageBorder(0),
mnBottomPageBorder(0),
mnVerticalGap (20),
mnHorizontalGap (20),
mnInsertionMarkerThickness (4),
mnTotalVerticalGap(0),
mnTotalHorizontalGap(0),
mnMinimalWidth (100),
mnPreferredWidth (200),
mnMaximalWidth (300),
mnMinimalColumnCount (1),
mnMaximalColumnCount (5),
mnColumnCount (1),
maPageObjectModelSize (1,1),
maPageObjectPixelSize (1,1)
{
}
Layouter::~Layouter (void)
{
}
void Layouter::SetObjectWidth (
sal_Int32 nMinimalWidth,
sal_Int32 nMaximalWidth,
sal_Int32 nPreferredWidth)
{
if (nMinimalWidth <= nPreferredWidth && nPreferredWidth <= nMaximalWidth)
{
mnMinimalWidth = nMinimalWidth;
mnPreferredWidth = nMaximalWidth;
mnMaximalWidth = nPreferredWidth;
}
}
void Layouter::SetBorders (
sal_Int32 nLeftBorder,
sal_Int32 nRightBorder,
sal_Int32 nTopBorder,
sal_Int32 nBottomBorder)
{
if (nLeftBorder >= 0)
mnRequestedLeftBorder.mnScreen = nLeftBorder;
if (nRightBorder >= 0)
mnRequestedRightBorder.mnScreen = nRightBorder;
if (nTopBorder >= 0)
mnRequestedTopBorder.mnScreen = nTopBorder;
if (nBottomBorder >= 0)
mnRequestedBottomBorder.mnScreen = nBottomBorder;
}
void Layouter::SetPageBorders (
sal_Int32 nLeftBorder,
sal_Int32 nRightBorder,
sal_Int32 nTopBorder,
sal_Int32 nBottomBorder)
{
if (nLeftBorder >= 0)
mnLeftPageBorder.mnScreen = nLeftBorder;
if (nRightBorder >= 0)
mnRightPageBorder.mnScreen = nRightBorder;
if (nTopBorder >= 0)
mnTopPageBorder.mnScreen = nTopBorder;
if (nBottomBorder >= 0)
mnBottomPageBorder.mnScreen = nBottomBorder;
}
void Layouter::SetGaps (
sal_Int32 nHorizontalGap,
sal_Int32 nVerticalGap)
{
if (nHorizontalGap >= 0)
mnHorizontalGap.mnScreen = nHorizontalGap;
if (nVerticalGap >= 0)
mnVerticalGap.mnScreen = nVerticalGap;
}
void Layouter::SetColumnCount (
sal_Int32 nMinimalColumnCount,
sal_Int32 nMaximalColumnCount)
{
if (nMinimalColumnCount <= nMaximalColumnCount)
{
mnMinimalColumnCount = nMinimalColumnCount;
mnMaximalColumnCount = nMaximalColumnCount;
}
}
bool Layouter::RearrangeHorizontal (
const Size& rWindowSize,
const Size& rPageObjectSize,
OutputDevice* pDevice,
const sal_uInt32 nPageCount)
{
if (rWindowSize.Width() > 0
&& rWindowSize.Height() > 0
&& rPageObjectSize.Width() > 0
&& rPageObjectSize.Height() > 0)
{
mnTotalHorizontalGap.mnScreen = mnHorizontalGap.mnScreen
+ mnRightPageBorder.mnScreen + mnLeftPageBorder.mnScreen;
mnTotalVerticalGap.mnScreen = mnVerticalGap.mnScreen
+ mnTopPageBorder.mnScreen + mnBottomPageBorder.mnScreen;
// Calculate the column count.
mnColumnCount = nPageCount;
// Update the border values. The insertion marker has to have space.
mnLeftBorder.mnScreen = mnRequestedLeftBorder.mnScreen;
mnTopBorder.mnScreen = mnRequestedTopBorder.mnScreen;
mnRightBorder.mnScreen = mnRequestedRightBorder.mnScreen;
mnBottomBorder.mnScreen = mnRequestedBottomBorder.mnScreen;
if (mnColumnCount > 1)
{
int nMinimumBorderWidth = mnInsertionMarkerThickness.mnScreen
+ mnHorizontalGap.mnScreen/2;
if (mnLeftBorder.mnScreen < nMinimumBorderWidth)
mnLeftBorder.mnScreen = nMinimumBorderWidth;
if (mnRightBorder.mnScreen < nMinimumBorderWidth)
mnRightBorder.mnScreen = nMinimumBorderWidth;
}
else
{
int nMinimumBorderHeight = mnInsertionMarkerThickness.mnScreen
+ mnVerticalGap.mnScreen/2;
if (mnTopBorder.mnScreen < nMinimumBorderHeight)
mnTopBorder.mnScreen = nMinimumBorderHeight;
if (mnBottomBorder.mnScreen < nMinimumBorderHeight)
mnBottomBorder.mnScreen = nMinimumBorderHeight;
}
// Calculate the width of each page object.
sal_uInt32 nTargetHeight = 0;
sal_uInt32 nRowCount = 1;
if (mnColumnCount > 0)
nTargetHeight = (rWindowSize.Height()
- mnTopBorder.mnScreen
- mnBottomBorder.mnScreen
- nRowCount * (mnTopPageBorder.mnScreen
+ mnBottomPageBorder.mnScreen)
- (nRowCount-1) * mnTotalVerticalGap.mnScreen
)
/ nRowCount;
sal_uInt32 nMinimalHeight (
mnMinimalWidth * rPageObjectSize.Height() / rPageObjectSize.Width());
sal_uInt32 nMaximalHeight (
mnMaximalWidth * rPageObjectSize.Height() / rPageObjectSize.Width());
if (nTargetHeight < nMinimalHeight)
nTargetHeight = nMinimalHeight;
if (nTargetHeight > nMaximalHeight)
nTargetHeight = nMaximalHeight;
// Initialize the device with some arbitrary zoom factor just in
// case that the current zoom factor is numerically instable when
// used in a multiplication.
MapMode aMapMode (pDevice->GetMapMode());
aMapMode.SetScaleX (Fraction(1,1));
aMapMode.SetScaleY (Fraction(1,1));
pDevice->SetMapMode (aMapMode);
// Calculate the resulting scale factor and the page object size in
// pixels.
maPageObjectModelSize = rPageObjectSize;
int nPagePixelHeight (pDevice->LogicToPixel(maPageObjectModelSize).Height());
// Adapt the layout of the given output device to the new layout of
// page objects. The zoom factor is set so that the page objects in
// one column fill the screen.
Fraction aScaleFactor (nTargetHeight, nPagePixelHeight);
SetZoom (aMapMode.GetScaleX() * aScaleFactor, pDevice);
return true;
}
else
return false;
}
bool Layouter::RearrangeVertical (
const Size& rWindowSize,
const Size& rPageObjectSize,
OutputDevice* pDevice)
{
if (rWindowSize.Width() > 0
&& rWindowSize.Height() > 0
&& rPageObjectSize.Width() > 0
&& rPageObjectSize.Height() > 0)
{
mnTotalHorizontalGap.mnScreen = mnHorizontalGap.mnScreen
+ mnRightPageBorder.mnScreen + mnLeftPageBorder.mnScreen;
mnTotalVerticalGap.mnScreen = mnVerticalGap.mnScreen
+ mnTopPageBorder.mnScreen + mnBottomPageBorder.mnScreen;
// Calculate the column count.
mnColumnCount = (rWindowSize.Width()
- mnRequestedLeftBorder.mnScreen - mnRequestedRightBorder.mnScreen)
/ (mnPreferredWidth + mnTotalHorizontalGap.mnScreen);
if (mnColumnCount < mnMinimalColumnCount)
mnColumnCount = mnMinimalColumnCount;
if (mnColumnCount > mnMaximalColumnCount)
mnColumnCount = mnMaximalColumnCount;
// Update the border values. The insertion marker has to have space.
mnLeftBorder.mnScreen = mnRequestedLeftBorder.mnScreen;
mnTopBorder.mnScreen = mnRequestedTopBorder.mnScreen;
mnRightBorder.mnScreen = mnRequestedRightBorder.mnScreen;
mnBottomBorder.mnScreen = mnRequestedBottomBorder.mnScreen;
if (mnColumnCount > 1)
{
int nMinimumBorderWidth = mnInsertionMarkerThickness.mnScreen
+ mnHorizontalGap.mnScreen/2;
if (mnLeftBorder.mnScreen < nMinimumBorderWidth)
mnLeftBorder.mnScreen = nMinimumBorderWidth;
if (mnRightBorder.mnScreen < nMinimumBorderWidth)
mnRightBorder.mnScreen = nMinimumBorderWidth;
}
else
{
int nMinimumBorderHeight = mnInsertionMarkerThickness.mnScreen
+ mnVerticalGap.mnScreen/2;
if (mnTopBorder.mnScreen < nMinimumBorderHeight)
mnTopBorder.mnScreen = nMinimumBorderHeight;
if (mnBottomBorder.mnScreen < nMinimumBorderHeight)
mnBottomBorder.mnScreen = nMinimumBorderHeight;
}
// Calculate the width of each page object.
sal_Int32 nTargetWidth = 0;
if (mnColumnCount > 0)
nTargetWidth = (rWindowSize.Width()
- mnLeftBorder.mnScreen
- mnRightBorder.mnScreen
- mnColumnCount * (mnRightPageBorder.mnScreen
+ mnLeftPageBorder.mnScreen)
- (mnColumnCount-1) * mnTotalHorizontalGap.mnScreen
)
/ mnColumnCount;
if (nTargetWidth < mnMinimalWidth)
nTargetWidth = mnMinimalWidth;
if (nTargetWidth > mnMaximalWidth)
nTargetWidth = mnMaximalWidth;
// Initialize the device with some arbitrary zoom factor just in
// case that the current zoom factor is numerically instable when
// used in a multiplication.
MapMode aMapMode (pDevice->GetMapMode());
aMapMode.SetScaleX (Fraction(1,1));
aMapMode.SetScaleY (Fraction(1,1));
pDevice->SetMapMode (aMapMode);
// Calculate the resulting scale factor and the page object size in
// pixels.
maPageObjectModelSize = rPageObjectSize;
int nPagePixelWidth (pDevice->LogicToPixel (maPageObjectModelSize).Width());
// Adapt the layout of the given output device to the new layout of
// page objects. The zoom factor is set so that the page objects in
// one row fill the screen.
Fraction aScaleFactor (nTargetWidth, nPagePixelWidth);
SetZoom (aMapMode.GetScaleX() * aScaleFactor, pDevice);
return true;
}
else
return false;
}
void Layouter::SetZoom (double nZoomFactor, OutputDevice* pDevice)
{
SetZoom(Fraction(nZoomFactor), pDevice);
}
void Layouter::SetZoom (Fraction nZoomFactor, OutputDevice* pDevice)
{
MapMode aMapMode (pDevice->GetMapMode());
aMapMode.SetScaleX (nZoomFactor);
aMapMode.SetScaleY (nZoomFactor);
maPageObjectPixelSize = pDevice->LogicToPixel (maPageObjectModelSize);
pDevice->SetMapMode (aMapMode);
// Transform frequently used values from pixel to model coordinates.
Size aTotalGap (pDevice->PixelToLogic (Size (
mnTotalHorizontalGap.mnScreen,
mnTotalVerticalGap.mnScreen)));
mnTotalHorizontalGap.mnModel = aTotalGap.Width();
mnTotalVerticalGap.mnModel = aTotalGap.Height();
Size aGap (pDevice->PixelToLogic (Size (
mnHorizontalGap.mnScreen,
mnVerticalGap.mnScreen)));
mnHorizontalGap.mnModel = aGap.Width();
mnVerticalGap.mnModel = aGap.Height();
Size aTopLeftBorder (pDevice->PixelToLogic (Size (
mnLeftBorder.mnScreen,
mnTopBorder.mnScreen)));
mnLeftBorder.mnModel = aTopLeftBorder.Width();
mnTopBorder.mnModel = aTopLeftBorder.Height();
Size aBottomRightBorder (pDevice->PixelToLogic (Size (
mnLeftBorder.mnScreen,
mnTopBorder.mnScreen)));
mnRightBorder.mnModel = aBottomRightBorder.Width();
mnBottomBorder.mnModel = aBottomRightBorder.Height();
Size aTopLeftPageBorder (pDevice->PixelToLogic (Size (
mnLeftPageBorder.mnScreen,
mnTopPageBorder.mnScreen)));
mnLeftPageBorder.mnModel = aTopLeftPageBorder.Width();
mnTopPageBorder.mnModel = aTopLeftPageBorder.Height();
Size aBottomRightPageBorder (pDevice->PixelToLogic (Size (
mnRightPageBorder.mnScreen,
mnBottomPageBorder.mnScreen)));
mnRightPageBorder.mnModel = aBottomRightPageBorder.Width();
mnBottomPageBorder.mnModel = aBottomRightPageBorder.Height();
mnInsertionMarkerThickness.mnModel = pDevice->PixelToLogic (
Size(mnInsertionMarkerThickness.mnScreen,0)).Width();
}
sal_Int32 Layouter::GetColumnCount (void) const
{
return mnColumnCount;
}
bool Layouter::IsColumnCountFixed (void) const
{
return mnMinimalColumnCount == mnMaximalColumnCount;
}
Size Layouter::GetPageObjectSize (void) const
{
return maPageObjectModelSize;
}
Rectangle Layouter::GetPageObjectBox (sal_Int32 nIndex) const
{
int nColumn = nIndex % mnColumnCount;
int nRow = nIndex / mnColumnCount;
return Rectangle (
Point (mnLeftBorder.mnModel
+ nColumn * maPageObjectModelSize.Width()
+ mnLeftPageBorder.mnModel
+ (nColumn>0 ? nColumn : 0) * mnTotalHorizontalGap.mnModel,
mnTopBorder.mnModel
+ nRow * maPageObjectModelSize.Height()
+ mnTopPageBorder.mnModel
+ (nRow>0 ? nRow : 0) * mnTotalVerticalGap.mnModel),
maPageObjectModelSize);
}
Rectangle Layouter::GetPageBox (sal_Int32 nObjectCount) const
{
sal_Int32 nHorizontalSize = 0;
sal_Int32 nVerticalSize = 0;
if (mnColumnCount > 0)
{
sal_Int32 nRowCount = (nObjectCount+mnColumnCount-1) / mnColumnCount;
nHorizontalSize =
mnLeftBorder.mnModel
+ mnRightBorder.mnModel
+ mnColumnCount * maPageObjectModelSize.Width()
+ mnLeftPageBorder.mnModel + mnRightPageBorder.mnModel;
if (mnColumnCount > 1)
nHorizontalSize
+= (mnColumnCount-1) * mnTotalHorizontalGap.mnModel;
nVerticalSize =
mnTopBorder.mnModel
+ mnBottomBorder.mnModel
+ nRowCount * maPageObjectModelSize.Height()
+ mnTopPageBorder.mnModel + mnBottomPageBorder.mnModel;
if (nRowCount > 1)
nVerticalSize += (nRowCount-1) * mnTotalVerticalGap.mnModel;
}
return Rectangle (
Point(0,0),
Size (nHorizontalSize, nVerticalSize)
);
}
Rectangle Layouter::GetInsertionMarkerBox (
sal_Int32 nIndex,
bool bVertical,
bool bLeftOrTop) const
{
Rectangle aBox (GetPageObjectBox (nIndex));
if (bVertical)
{
sal_Int32 nHorizontalInsertionMarkerOffset
= (mnHorizontalGap.mnModel-mnInsertionMarkerThickness.mnModel) / 2;
if (bLeftOrTop)
{
// Left.
aBox.Left() -= mnLeftPageBorder.mnModel
+ mnHorizontalGap.mnModel
- nHorizontalInsertionMarkerOffset;
}
else
{
// Right.
aBox.Left() = aBox.Right()
+ mnRightPageBorder.mnModel
+ nHorizontalInsertionMarkerOffset;
}
aBox.Right() = aBox.Left() + mnInsertionMarkerThickness.mnModel;
}
else
{
sal_Int32 nVerticalInsertionMarkerOffset
= (mnVerticalGap.mnModel - mnInsertionMarkerThickness.mnModel) / 2;
if (bLeftOrTop)
{
// Above.
aBox.Top() -= mnTopPageBorder.mnModel
+ mnVerticalGap.mnModel
- nVerticalInsertionMarkerOffset;
}
else
{
// Below.
aBox.Top() = aBox.Bottom()
+ mnBottomPageBorder.mnModel
+ nVerticalInsertionMarkerOffset;
}
aBox.Bottom() = aBox.Top() + mnInsertionMarkerThickness.mnModel;
}
return aBox;
}
sal_Int32 Layouter::GetIndexOfFirstVisiblePageObject (
const Rectangle& aVisibleArea) const
{
sal_Int32 nRow = GetRowAtPosition (aVisibleArea.Top(), true, GM_BOTH);
return nRow * mnColumnCount;
}
sal_Int32 Layouter::GetIndexOfLastVisiblePageObject (
const Rectangle& aVisibleArea) const
{
sal_Int32 nRow = GetRowAtPosition (aVisibleArea.Bottom(),
true, GM_BOTH);
return (nRow+1) * mnColumnCount - 1;
}
sal_Int32 Layouter::GetIndexAtPoint (
const Point& rPosition,
bool bIncludePageBorders) const
{
sal_Int32 nRow = GetRowAtPosition (rPosition.Y(),
bIncludePageBorders,
bIncludePageBorders ? GM_PAGE_BORDER : GM_NONE);
sal_Int32 nColumn = GetColumnAtPosition (rPosition.X(),
bIncludePageBorders,
bIncludePageBorders ? GM_PAGE_BORDER : GM_NONE);
if (nRow >= 0 && nColumn >= 0)
return nRow * mnColumnCount + nColumn;
else
return -1;
}
/** Calculation of the insertion index:
1. Determine the row. rPoint has to be in the row between upper and
lower border. If it is in a horizontal gap or border an invalid
insertion index (-1, which is a valid return value) will be returned.
2. Determine the column. Here both vertical borders and vertical gaps
will yield valid return values. The horizontal positions between the
center of page objects in column i and the center of page objects in
column i+1 will return column i+1 as insertion index.
When there is only one column and bAllowVerticalPosition is true than
take the vertical areas between rows into account as well.
*/
sal_Int32 Layouter::GetInsertionIndex (
const Point& rPosition,
bool bAllowVerticalPosition) const
{
sal_Int32 nIndex = -1;
sal_Int32 nRow = GetRowAtPosition (rPosition.Y(), true,
(mnColumnCount==1 && bAllowVerticalPosition) ? GM_BOTH : GM_BOTH);
sal_Int32 nColumn = GetColumnAtPosition (rPosition.X(), true, GM_BOTH);
if (nRow >= 0 && nColumn >= 0)
nIndex = nRow * mnColumnCount + nColumn;
return nIndex;
}
Layouter::DoublePoint
Layouter::ConvertModelToLayouterCoordinates (
const Point& rModelPoint) const
{
sal_Int32 nColumn = GetColumnAtPosition (rModelPoint.X(), true, GM_BOTH);
sal_Int32 nColumnWidth
= maPageObjectModelSize.Width() + mnTotalHorizontalGap.mnModel;
sal_Int32 nDistanceIntoColumn =
rModelPoint.X() - mnLeftBorder.mnModel - mnLeftPageBorder.mnModel
- nColumn * nColumnWidth;
sal_Int32 nRow = GetRowAtPosition (rModelPoint.Y(), true, GM_BOTH);
sal_Int32 nRowHeight
= maPageObjectModelSize.Height() + mnTotalVerticalGap.mnModel;
sal_Int32 nDistanceIntoRow =
rModelPoint.Y() - mnTopBorder.mnModel - mnTopPageBorder.mnModel
- nRow * nRowHeight;
return DoublePoint (
nColumn + double(nDistanceIntoColumn) / double(nColumnWidth),
nRow + double(nDistanceIntoRow) / double(nRowHeight));
}
Point Layouter::ConvertLayouterToModelCoordinates (
const DoublePoint & rLayouterPoint) const
{
sal_Int32 nColumn = (sal_Int32) ::rtl::math::round(rLayouterPoint.first,
0,rtl_math_RoundingMode_Floor);
sal_Int32 nColumnWidth
= maPageObjectModelSize.Width() + mnTotalHorizontalGap.mnModel;
sal_Int32 nDistanceIntoColumn
= (sal_Int32)((rLayouterPoint.first - nColumn) * nColumnWidth);
sal_Int32 nRow = (sal_Int32) ::rtl::math::round(rLayouterPoint.second,
0,rtl_math_RoundingMode_Floor);
sal_Int32 nRowHeight
= maPageObjectModelSize.Height() + mnTotalVerticalGap.mnModel;
sal_Int32 nDistanceIntoRow
= (sal_Int32)((rLayouterPoint.second - nRow) * nRowHeight);
return Point (
mnLeftBorder.mnModel + mnLeftPageBorder.mnModel
+ nColumn * nColumnWidth + nDistanceIntoColumn,
mnTopBorder.mnModel + mnTopPageBorder.mnModel
+ nRow * nRowHeight + nDistanceIntoRow);
}
sal_Int32 Layouter::GetRowAtPosition (
sal_Int32 nYPosition,
bool bIncludeBordersAndGaps,
GapMembership eGapMembership) const
{
sal_Int32 nRow = -1;
const sal_Int32 nY = nYPosition
- mnTopBorder.mnModel - mnTopPageBorder.mnModel;
if (nY >= 0)
{
// Vertical distance from one row to the next.
const sal_Int32 nRowOffset (
maPageObjectModelSize.Height() + mnTotalVerticalGap.mnModel);
// Calculate row consisting of page objects and gap below.
nRow = nY / nRowOffset;
const sal_Int32 nDistanceIntoGap (
(nY - nRow*nRowOffset) - maPageObjectModelSize.Height());
// When inside the gap below then nYPosition is not over a page
// object.
if (nDistanceIntoGap > 0)
nRow = ResolvePositionInGap (
nDistanceIntoGap,
eGapMembership,
nRow,
mnBottomPageBorder.mnModel,
mnVerticalGap.mnModel);
}
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::GetColumnAtPosition (
sal_Int32 nXPosition,
bool bIncludeBordersAndGaps,
GapMembership eGapMembership) const
{
sal_Int32 nColumn = -1;
sal_Int32 nX = nXPosition
- mnLeftBorder.mnModel - mnLeftPageBorder.mnModel;
if (nX >= 0)
{
// Horizontal distance from one column to the next.
const sal_Int32 nColumnOffset (
maPageObjectModelSize.Width() + mnTotalHorizontalGap.mnModel);
// 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) - maPageObjectModelSize.Width());
// When inside the gap at the right then nXPosition is not over a
// page object.
if (nDistanceIntoGap > 0)
nColumn = ResolvePositionInGap (
nDistanceIntoGap,
eGapMembership,
nColumn,
mnRightPageBorder.mnModel,
mnHorizontalGap.mnModel);
}
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::ResolvePositionInGap (
sal_Int32 nDistanceIntoGap,
GapMembership eGapMembership,
sal_Int32 nIndex,
sal_Int32 nLeftOrTopPageBorder,
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 = nLeftOrTopPageBorder + 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 > nLeftOrTopPageBorder)
{
if (nDistanceIntoGap > nLeftOrTopPageBorder + 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;
}
const Layouter::BackgroundRectangleList&
Layouter::GetBackgroundRectangleList (void) const
{
return maBackgroundRectangleList;
}
} } } // end of namespace ::sd::slidesorter::namespace