/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
class Layouter::Implementation
{ public:
VclPtr<sd::Window> mpWindow; staticconst sal_Int32 mnRequestedLeftBorder = 5; staticconst sal_Int32 mnRequestedRightBorder = 5; staticconst sal_Int32 mnRequestedTopBorder = 5; staticconst sal_Int32 mnRequestedBottomBorder = 5;
sal_Int32 mnLeftBorder;
sal_Int32 mnRightBorder;
sal_Int32 mnTopBorder;
sal_Int32 mnBottomBorder; staticconst sal_Int32 gnVerticalGap = 10 - 2*Theme_FocusIndicatorWidth; staticconst sal_Int32 gnHorizontalGap = 10 - 2*Theme_FocusIndicatorWidth;
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;
std::shared_ptr<PageObjectLayouter> mpPageObjectLayouter;
std::shared_ptr<view::Theme> mpTheme;
/** Specify how the gap between two page objects is associated with the page objects.
*/ enumclass GapMembership {
None, // Gap is not associated with any page object.
Previous, // The whole gap is associated with the previous page // object (left or above the gap.)
Both, // Half of the gap is associated with previous, half // with the next page object.
Next // The whole gap is associated with the next page // object (right or below the gap.)
};
/** 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 GapMembership::None corresponds to bIncludeBordersAndGaps being <FALSE/>. When GapMembership::Both is given then the upper half is associated to the row above and the lower half to the row below. Values of GapMembership::Previous and GapMembership::Next associate the whole gap area with the row above or below respectively.
*/
sal_Int32 GetRowAtPosition (
sal_Int32 nYPosition, bool bIncludeBordersAndGaps,
GapMembership eGapMembership) const;
/** Calculate the column that the point with the given horizontal coordinate is over. The vertical 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) 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 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 coordinates 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.
*/ static sal_Int32 ResolvePositionInGap (
sal_Int32 nDistanceIntoGap,
GapMembership eGapMembership,
sal_Int32 nIndex,
sal_Int32 nGap);
/** Calculate the logical part of the insert position, i.e. the page after which to insert.
*/ virtualvoid 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, constbool bIsVertical,
model::SlideSorterModel const & 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.
*/
::tools::Rectangle GetInnerBoundingBox (
model::SlideSorterModel const & rModel, const sal_Int32 nIndex) const;
Range GetValidHorizontalSizeRange() const;
Range GetValidVerticalSizeRange() const;
/** The vertical layouter has one column and as many rows as there are pages.
*/ class VerticalImplementation : public Layouter::Implementation
{ public: explicit VerticalImplementation (const Implementation& rImplementation);
/** The horizontal layouter has one row and as many columns as there are pages.
*/ class HorizontalImplementation : public Layouter::Implementation
{ public: explicit HorizontalImplementation(const Implementation& rImplementation);
/** 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 (
sd::Window *pWindow, const std::shared_ptr<view::Theme>& rpTheme); explicit GridImplementation(const Implementation& rImplementation);
// Return early when the window or the model have not yet been initialized. if (rWindowSize.IsEmpty()) returnfalse; if (rPreviewModelSize.IsEmpty()) returnfalse;
CalculateRowAndColumnCount(rWindowSize);
// Update the border values.
mnLeftBorder = mnRequestedLeftBorder;
mnTopBorder = mnRequestedTopBorder;
mnRightBorder = mnRequestedRightBorder;
mnBottomBorder = mnRequestedBottomBorder; if (mnColumnCount > 1)
{ int nMinimumBorderWidth = gnHorizontalGap/2; if (mnLeftBorder < nMinimumBorderWidth)
mnLeftBorder = nMinimumBorderWidth; if (mnRightBorder < nMinimumBorderWidth)
mnRightBorder = nMinimumBorderWidth;
} else
{ int nMinimumBorderHeight = gnVerticalGap/2; if (mnTopBorder < nMinimumBorderHeight)
mnTopBorder = nMinimumBorderHeight; if (mnBottomBorder < nMinimumBorderHeight)
mnBottomBorder = nMinimumBorderHeight;
}
const sal_Int32 nY = nYPosition - mnTopBorder; if (nY >= 0)
{ // Vertical distance from one row to the next. const sal_Int32 nRowOffset (maPageObjectSize.Height() + gnVerticalGap);
// 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)
{
sal_Int32 nResolvedRow = ResolvePositionInGap(
nDistanceIntoGap,
eGapMembership,
nRow,
gnVerticalGap); if (!bIncludeBordersAndGaps || nResolvedRow != -1)
nRow = nResolvedRow;
}
} elseif (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;
}
sal_Int32 nX = nXPosition - mnLeftBorder; if (nX >= 0)
{ // Horizontal distance from one column to the next. const sal_Int32 nColumnOffset (maPageObjectSize.Width() + gnHorizontalGap);
// Calculate row consisting of page objects and gap below.
nColumn = nX / nColumnOffset; if (nColumn < 0)
nColumn = 0; elseif (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)
{
sal_Int32 nResolvedColumn = ResolvePositionInGap(
nDistanceIntoGap,
eGapMembership,
nColumn,
gnHorizontalGap); if (!bIncludeBordersAndGaps || nResolvedColumn != -1)
nColumn = nResolvedColumn;
}
} elseif (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)
{ switch (eGapMembership)
{ case GapMembership::None: // The gap is no man's land.
nIndex = -1; break;
case GapMembership::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 GapMembership::Previous: // Row or column already at correct value. break;
case GapMembership::Next: // The complete gap belongs to the next row or column.
nIndex ++; break;
default:
nIndex = -1;
}
return nIndex;
}
void Layouter::Implementation::CalculateGeometricPosition (
InsertPosition& rPosition, const Size& rIndicatorSize, constbool bIsVertical,
model::SlideSorterModel const & 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 ::tools::Rectangle aOuterBox (GetPageObjectBox(nIndex)); const ::tools::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;
} elseif (rPosition.IsAtRunEnd())
{ // Place indicator at the bottom/right of the column/row.
Range Layouter::Implementation::GetRangeOfVisiblePageObjects (const ::tools::Rectangle& aVisibleArea) const
{ // technically that's not empty, but it's the default, so... if (aVisibleArea.IsEmpty()) return Range(-1, -1);
// 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));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.