📄 staticlayoutmanager.java
字号:
/**
* ========================================
* JFreeReport : a free Java report library
* ========================================
*
* Project Info: http://www.jfree.org/jfreereport/index.html
* Project Lead: Thomas Morgner;
*
* (C) Copyright 2000-2003, by Simba Management Limited and Contributors.
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* ------------------------
* StaticLayoutManager.java
* ------------------------
* (C)opyright 2002, 2003, by Thomas Morgner and Contributors.
*
* Original Author: Thomas Morgner;
* Contributor(s): David Gilbert (for Simba Management Limited);
*
* $Id: StaticLayoutManager.java,v 1.13 2003/11/12 22:40:03 taqua Exp $
*
* Changes
* -------
* 03-Dec-2002 : Javadocs (DG);
* 21-Jan-2003 : removed ABSOLUTE_DIM StyleKey. The beast would cause trouble.
* 01-Feb-2003 : BugFix: Layouting was not correct for subbands.
* 24-Mar-2003 : Invisible bands will be layouted, invisible childs will be ignored.
*/
package org.jfree.report.layout;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.jfree.report.Band;
import org.jfree.report.Element;
import org.jfree.report.style.ElementStyleSheet;
import org.jfree.report.style.StyleKey;
import org.jfree.report.util.ElementLayoutInformation;
import org.jfree.ui.FloatDimension;
/**
* An implementation of the BandLayoutManager interface.
* <p>
* Rule: Bands can have minimum, max and pref size defined. These values are hints for
* the layout container, no restrictions. If min and pref are '0', they are ignored.
* MaxSize is never ignored.
* <p>
* Elements that have the "dynamic" flag set, are checked for their content-bounds.
* This operation is expensive, so this is only done if really needed. The dynamic
* flag will influence the height of an element, a valid width must be already set.
* <p>
* Invisible elements within the layouted band are not evaluated. This layout manager
* will ignore invisible child bands and -elements.
* <p>
* Note to everybody who tries to understand this class: This class is full of old
* compatibility code, this class is not designed to be smart, or suitable for complex
* layouts. The only purpose of this class is to maintain backward compatiblity with
* older releases of JFreeReport.
* <p>
* The use of relative elements (the one's with 100% should be considered carefully,
* as these elements are not fully predictable).
*
* @author Thomas Morgner
*/
public strictfp class StaticLayoutManager extends AbstractBandLayoutManager
{
/** A key for the absolute position of an element. */
public static final StyleKey ABSOLUTE_POS = StyleKey.getStyleKey("absolute_pos", Point2D.class);
/** The default position. */
private static final Point2D DEFAULT_POS = new Point2D.Float(0, 0);
/** A cache. */
private final LayoutManagerCache cache;
/** A cache key. */
private final LayoutSearchKey cacheKey;
/**
* Creates a new layout manager.
*/
public StaticLayoutManager()
{
cache = new LayoutManagerCache();
cacheKey = new LayoutSearchKey();
}
/**
* Returns the minimum size for an element.
*
* @param e the element.
* @param containerBounds the bounds of the elements parents.
* @param retval a dimension object that should be filled, or null,
* if a new object should be created
* @param support the layout support used to compute sizes.
*
* @return the minimum size.
*/
protected Dimension2D computeMinimumSize(final Element e, final Dimension2D containerBounds,
Dimension2D retval, final LayoutSupport support)
{
final boolean isCacheable = cache.isCachable(e);
if (isCacheable)
{
cacheKey.setSearchConstraint(e, containerBounds);
final Dimension2D cretval = cache.getMinSize(cacheKey);
if (cretval != null)
{
return cretval;
}
}
// the absolute position of the element within its parent is used
// to calculate the maximum available space for the element.
final Point2D absPos = (Point2D)
e.getStyle().getStyleProperty(ABSOLUTE_POS, DEFAULT_POS);
final float absPosX = correctRelativeValue((float) absPos.getX(),
(float) containerBounds.getWidth());
final float absPosY = correctRelativeValue((float) absPos.getY(),
(float) containerBounds.getHeight());
if (containerBounds.getWidth() < absPosX)
{
// Element is not within the range of the container. Abort, Retry, Ignore?
throw new IllegalStateException("Width violation!");
}
if (containerBounds.getHeight() < absPosY)
{
// Element is not within the range of the container. Abort, Retry, Ignore?
throw new IllegalStateException("Height violation!");
}
// if this is a band, then try to calculate the min-size
if (e instanceof Band)
{
final BandLayoutManager lm = BandLayoutManagerUtil.getLayoutManager(e);
retval = lm.minimumLayoutSize((Band) e, containerBounds, support);
}
else
{
// return the minimum size as fallback
final Dimension2D dim = (Dimension2D)
e.getStyle().getStyleProperty(ElementStyleSheet.MINIMUMSIZE);
retval = correctDimension(dim, containerBounds, retval);
}
// now apply the maximum bounds to the retval.
// the maximum bounds are defined by the element and the elements container.
final Dimension2D maxSize = correctDimension((Dimension2D)
e.getStyle().getStyleProperty(ElementStyleSheet.MAXIMUMSIZE), containerBounds, null);
maxSize.setSize(Math.min(containerBounds.getWidth() - absPosX, maxSize.getWidth()),
Math.min(containerBounds.getHeight() - absPosY, maxSize.getHeight()));
if (e.getStyle().getBooleanStyleProperty(ElementStyleSheet.DYNAMIC_HEIGHT))
{
retval = getElementContentBounds(retval, e, maxSize, support);
}
retval.setSize(Math.min(retval.getWidth(), maxSize.getWidth()),
Math.min(retval.getHeight(), maxSize.getHeight()));
//Log.debug ("-- calculate MinimumSize: " + retval);
// layouting has failed, if negative values are returned ... !
if (retval.getWidth() < 0 || retval.getHeight() < 0)
{
throw new IllegalStateException
("Layouting failed, computeMinimumSize returned negative values.");
}
if (isCacheable)
{
cache.setMinSize(cacheKey, e, retval);
}
return retval;
}
/**
* Calculates the preferred size of an element.
*
* @param e the element.
* @param containerBounds the bounds of the element's container.
* @param retval a dimension object that should be filled, or null,
* if a new object should be created
* @param support the layout support used to compute sizes.
*
* @return the preferred size of the element.
*/
protected Dimension2D computePreferredSize(final Element e,
final Dimension2D containerBounds, Dimension2D retval, LayoutSupport support)
{
final boolean isCachable = cache.isCachable(e);
if (isCachable)
{
cacheKey.setSearchConstraint(e, containerBounds);
final Dimension2D cretval = cache.getMinSize(cacheKey);
if (cretval != null)
{
// Log.debug ("+" + cretval);
return cretval;
}
}
// the absolute position of the element within its parent is used
// to calculate the maximum available space for the element.
final Point2D absPos = (Point2D)
e.getStyle().getStyleProperty(ABSOLUTE_POS, DEFAULT_POS);
final float absPosX = correctRelativeValue((float) absPos.getX(),
(float) containerBounds.getWidth());
final float absPosY = correctRelativeValue((float) absPos.getY(),
(float) containerBounds.getHeight());
if (containerBounds.getWidth() < absPosX)
{
// Element is not within the range of the container. Abort, Retry, Ignore?
throw new IllegalStateException("Width violation!");
}
if (containerBounds.getHeight() < absPosY)
{
// Element is not within the range of the container. Abort, Retry, Ignore?
throw new IllegalStateException("Height violation!");
}
// if e is a band, then try to calculate the preferred size
if (e instanceof Band)
{
final BandLayoutManager lm = BandLayoutManagerUtil.getLayoutManager(e);
retval = lm.preferredLayoutSize((Band) e, containerBounds, support);
}
else
{
// if prefsize is defined, return it
final Dimension2D d = (Dimension2D)
e.getStyle().getStyleProperty(ElementStyleSheet.PREFERREDSIZE);
if (d != null)
{
retval = correctDimension(d, containerBounds, retval);
}
else
{
// return the absolute dimension as fallback
retval = correctDimension((Dimension2D)
e.getStyle().getStyleProperty(ElementStyleSheet.MINIMUMSIZE), containerBounds, retval);
}
}
// now apply the maximum bounds to the retval.
// the maximum bounds are defined by the element and the elements container.
final Dimension2D maxSize = correctDimension(
(Dimension2D) e.getStyle().getStyleProperty(ElementStyleSheet.MAXIMUMSIZE),
containerBounds, null);
maxSize.setSize(Math.min(containerBounds.getWidth() - absPosX, maxSize.getWidth()),
Math.min(containerBounds.getHeight() - absPosY, maxSize.getHeight()));
if (e.getStyle().getBooleanStyleProperty(ElementStyleSheet.DYNAMIC_HEIGHT))
{
retval = getElementContentBounds(retval, e, maxSize, support);
}
retval.setSize(Math.min(retval.getWidth(), maxSize.getWidth()),
Math.min(retval.getHeight(), maxSize.getHeight()));
// layouting has failed, if negative values are returned ... !
if (retval.getWidth() < 0 || retval.getHeight() < 0)
{
throw new IllegalStateException(
"Layouting failed, computePreferredSize returned negative values." + e.getName());
}
if (isCachable)
{
cache.setPrefSize(cacheKey, e, retval);
}
//Log.debug ("+" + retval);
return retval;
}
/**
* Calculates the preferred layout size for a band. The band is limited
* to the given container bounds as well as to the own maximum size.
* <p>
* The preferred size of non-absolute elements is calculated by using the
* parents dimensions supplied in containerDims. Elements with a width or
* height of 100% will consume all available space of the parent.
*
* @param b the band.
* @param containerDims the maximum size the band should use for that container.
* @param support the layout support used to compute sizes.
*
* @return the preferred size.
*/
public Dimension2D preferredLayoutSize
(final Band b, final Dimension2D containerDims, final LayoutSupport support)
{
if (support == null)
{
throw new NullPointerException("LayoutSupport is null.");
}
if (b == null)
{
throw new NullPointerException("Band is null.");
}
if (containerDims == null)
{
throw new NullPointerException("ContainerBounds are null.");
}
synchronized (b.getTreeLock())
{
//Log.debug(">" + containerDims + " vs - " + b.getName());
final ElementLayoutInformation eli =
createLayoutInformationForPreferredSize(b, containerDims);
final Dimension2D maxSize = eli.getMaximumSize();
final Dimension2D minSize = eli.getMinimumSize();
final FloatDimension base = new FloatDimension
((float) maxSize.getWidth(), (float) maxSize.getHeight());
float height = (float) minSize.getHeight();
float width = (float) minSize.getWidth();
// Now adjust the defined sizes by using the elements stored in the band.
final Element[] elements = b.getElementArray();
final Dimension2D tmpResult = null;
// calculate absolute width
for (int i = 0; i < elements.length; i++)
{
final Element e = elements[i];
if (e.isVisible() == false)
{
continue;
}
final boolean staticWidth = isElementStaticWidth(e);
final boolean staticHeight = isElementStaticHeight(e);
if (staticWidth || staticHeight)
{
final Point2D absPos = (Point2D) e.getStyle().getStyleProperty(ABSOLUTE_POS, DEFAULT_POS);
// check whether the element would be visible .. if not visible, then
// dont do anything ...
if (absPos.getX() > maxSize.getWidth() || absPos.getY() > maxSize.getHeight())
{
// dont display, as this element is larger than the container ...
continue;
}
final Dimension2D absDim = computePreferredSize(e, base, tmpResult, support);
if (staticWidth)
{
width = (float) Math.max(absDim.getWidth() + absPos.getX(), width);
}
if (staticHeight)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -