/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package javax.swing;
import java.awt.
AWTError;
import java.awt.
LayoutManager;
import java.awt.
Component;
import java.awt.
Container;
import java.awt.
Rectangle;
import java.awt.
Point;
import java.awt.
Dimension;
import java.awt.
Insets;
import java.io.
Serializable;
/**
* The default layout manager for <code>JViewport</code>.
* <code>ViewportLayout</code> defines
* a policy for layout that should be useful for most applications.
* The viewport makes its view the same size as the viewport,
* however it will not make the view smaller than its minimum size.
* As the viewport grows the view is kept bottom justified until
* the entire view is visible, subsequently the view is kept top
* justified.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is
* appropriate for short term storage or RMI between applications running
* the same version of Swing. As of 1.4, support for long term storage
* of all JavaBeans™
* has been added to the <code>java.beans</code> package.
* Please see {@link java.beans.XMLEncoder}.
*
* @author Hans Muller
*/
public class
ViewportLayout implements
LayoutManager,
Serializable
{
// Single instance used by JViewport.
static
ViewportLayout SHARED_INSTANCE = new
ViewportLayout();
/**
* Adds the specified component to the layout. Not used by this class.
* @param name the name of the component
* @param c the the component to be added
*/
public void
addLayoutComponent(
String name,
Component c) { }
/**
* Removes the specified component from the layout. Not used by
* this class.
* @param c the component to remove
*/
public void
removeLayoutComponent(
Component c) { }
/**
* Returns the preferred dimensions for this layout given the components
* in the specified target container.
* @param parent the component which needs to be laid out
* @return a <code>Dimension</code> object containing the
* preferred dimensions
* @see #minimumLayoutSize
*/
public
Dimension preferredLayoutSize(
Container parent) {
Component view = ((
JViewport)
parent).
getView();
if (
view == null) {
return new
Dimension(0, 0);
}
else if (
view instanceof
Scrollable) {
return ((
Scrollable)
view).
getPreferredScrollableViewportSize();
}
else {
return
view.
getPreferredSize();
}
}
/**
* Returns the minimum dimensions needed to layout the components
* contained in the specified target container.
*
* @param parent the component which needs to be laid out
* @return a <code>Dimension</code> object containing the minimum
* dimensions
* @see #preferredLayoutSize
*/
public
Dimension minimumLayoutSize(
Container parent) {
return new
Dimension(4, 4);
}
/**
* Called by the AWT when the specified container needs to be laid out.
*
* @param parent the container to lay out
*
* @throws AWTError if the target isn't the container specified to the
* <code>BoxLayout</code> constructor
*/
public void
layoutContainer(
Container parent)
{
JViewport vp = (
JViewport)
parent;
Component view =
vp.
getView();
Scrollable scrollableView = null;
if (
view == null) {
return;
}
else if (
view instanceof
Scrollable) {
scrollableView = (
Scrollable)
view;
}
/* All of the dimensions below are in view coordinates, except
* vpSize which we're converting.
*/
Insets insets =
vp.
getInsets();
Dimension viewPrefSize =
view.
getPreferredSize();
Dimension vpSize =
vp.
getSize();
Dimension extentSize =
vp.
toViewCoordinates(
vpSize);
Dimension viewSize = new
Dimension(
viewPrefSize);
if (
scrollableView != null) {
if (
scrollableView.
getScrollableTracksViewportWidth()) {
viewSize.
width =
vpSize.
width;
}
if (
scrollableView.
getScrollableTracksViewportHeight()) {
viewSize.
height =
vpSize.
height;
}
}
Point viewPosition =
vp.
getViewPosition();
/* If the new viewport size would leave empty space to the
* right of the view, right justify the view or left justify
* the view when the width of the view is smaller than the
* container.
*/
if (
scrollableView == null ||
vp.
getParent() == null ||
vp.
getParent().
getComponentOrientation().
isLeftToRight()) {
if ((
viewPosition.
x +
extentSize.
width) >
viewSize.
width) {
viewPosition.
x =
Math.
max(0,
viewSize.
width -
extentSize.
width);
}
} else {
if (
extentSize.
width >
viewSize.
width) {
viewPosition.
x =
viewSize.
width -
extentSize.
width;
} else {
viewPosition.
x =
Math.
max(0,
Math.
min(
viewSize.
width -
extentSize.
width,
viewPosition.
x));
}
}
/* If the new viewport size would leave empty space below the
* view, bottom justify the view or top justify the view when
* the height of the view is smaller than the container.
*/
if ((
viewPosition.
y +
extentSize.
height) >
viewSize.
height) {
viewPosition.
y =
Math.
max(0,
viewSize.
height -
extentSize.
height);
}
/* If we haven't been advised about how the viewports size
* should change wrt to the viewport, i.e. if the view isn't
* an instance of Scrollable, then adjust the views size as follows.
*
* If the origin of the view is showing and the viewport is
* bigger than the views preferred size, then make the view
* the same size as the viewport.
*/
if (
scrollableView == null) {
if ((
viewPosition.
x == 0) && (
vpSize.
width >
viewPrefSize.
width)) {
viewSize.
width =
vpSize.
width;
}
if ((
viewPosition.
y == 0) && (
vpSize.
height >
viewPrefSize.
height)) {
viewSize.
height =
vpSize.
height;
}
}
vp.
setViewPosition(
viewPosition);
vp.
setViewSize(
viewSize);
}
}