3868442ba9
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.
816 lines
24 KiB
C++
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
|