home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 November
/
Chip_1998-11_cd.bin
/
tema
/
Cafe
/
jfc.bin
/
ScrollPaneLayout.java
< prev
next >
Wrap
Text File
|
1998-02-26
|
20KB
|
685 lines
/*
* @(#)ScrollPaneLayout.java 1.20 98/02/02
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package com.sun.java.swing;
import com.sun.java.swing.border.*;
import java.awt.LayoutManager;
import java.awt.Component;
import java.awt.Container;
import java.awt.Rectangle;
import java.awt.Dimension;
import java.awt.Insets;
import java.io.Serializable;
/**
* The layout manager used by JScrollPane. JScrollPaneLayout is
* responsible for nine components: a viewport, two scrollbars,
* a row header, a column header, and four "corner" components.
* <p>
* Warning: 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 Swing1.0 applications. It will
* not be possible to load serialized Swing1.0 objects with future releases
* of Swing. The JDK1.2 release of Swing will be the compatibility
* baseline for the serialized form of Swing objects.
*
* @version 1.20 02/02/98
* @author unknown
*/
public class ScrollPaneLayout
implements LayoutManager, ScrollPaneConstants, Serializable
{
protected JViewport viewport;
protected JScrollBar vsb;
protected JScrollBar hsb;
protected JViewport rowHead;
protected JViewport colHead;
protected Component lowerLeft;
protected Component lowerRight;
protected Component upperLeft;
protected Component upperRight;
protected int vsbPolicy = VERTICAL_SCROLLBAR_AS_NEEDED;
protected int hsbPolicy = HORIZONTAL_SCROLLBAR_AS_NEEDED;
/**
* Only one of these is allowed, remove the old one if neccessary.
*/
protected Component addSingletonComponent(Component oldC, Component newC)
{
if ((oldC != null) && (oldC != newC)) {
oldC.getParent().remove(oldC);
}
return newC;
}
public void addLayoutComponent(String s, Component c)
{
if (s.equals(VIEWPORT)) {
viewport = (JViewport)addSingletonComponent(viewport, c);
}
else if (s.equals(VERTICAL_SCROLLBAR)) {
vsb = (JScrollBar)addSingletonComponent(vsb, c);
}
else if (s.equals(HORIZONTAL_SCROLLBAR)) {
hsb = (JScrollBar)addSingletonComponent(hsb, c);
}
else if (s.equals(ROW_HEADER)) {
rowHead = (JViewport)addSingletonComponent(rowHead, c);
}
else if (s.equals(COLUMN_HEADER)) {
colHead = (JViewport)addSingletonComponent(colHead, c);
}
else if (s.equals(LOWER_LEFT_CORNER)) {
lowerLeft = addSingletonComponent(lowerLeft, c);
}
else if (s.equals(LOWER_RIGHT_CORNER)) {
lowerRight = addSingletonComponent(lowerRight, c);
}
else if (s.equals(UPPER_LEFT_CORNER)) {
upperLeft = addSingletonComponent(upperLeft, c);
}
else if (s.equals(UPPER_RIGHT_CORNER)) {
upperRight = addSingletonComponent(upperRight, c);
}
else {
throw new IllegalArgumentException("invalid layout key " + s);
}
}
public void removeLayoutComponent(Component c)
{
if (c == viewport) {
viewport = null;
}
else if (c == vsb) {
vsb = null;
}
else if (c == hsb) {
hsb = null;
}
else if (c == rowHead) {
rowHead = null;
}
else if (c == colHead) {
colHead = null;
}
else if (c == lowerLeft) {
lowerLeft = null;
}
else if (c == upperLeft) {
upperLeft = null;
}
else if (c == upperRight) {
upperRight = null;
}
}
public int getVerticalScrollBarPolicy() {
return vsbPolicy;
}
public void setVerticalScrollBarPolicy(int x) {
switch (x) {
case VERTICAL_SCROLLBAR_AS_NEEDED:
case VERTICAL_SCROLLBAR_NEVER:
case VERTICAL_SCROLLBAR_ALWAYS:
vsbPolicy = x;
break;
default:
throw new IllegalArgumentException("invalid verticalScrollBarPolicy");
}
}
public int getHorizontalScrollBarPolicy() {
return hsbPolicy;
}
public void setHorizontalScrollBarPolicy(int x) {
switch (x) {
case HORIZONTAL_SCROLLBAR_AS_NEEDED:
case HORIZONTAL_SCROLLBAR_NEVER:
case HORIZONTAL_SCROLLBAR_ALWAYS:
hsbPolicy = x;
break;
default:
throw new IllegalArgumentException("invalid horizontalScrollBarPolicy");
}
}
public JViewport getViewport() {
return viewport;
}
public JScrollBar getHorizontalScrollBar() {
return hsb;
}
public JScrollBar getVerticalScrollBar() {
return vsb;
}
public JViewport getRowHeader() {
return rowHead;
}
public JViewport getColumnHeader() {
return colHead;
}
public Component getCorner(String key) {
if (key.equals(LOWER_LEFT_CORNER)) {
return lowerLeft;
}
else if (key.equals(LOWER_RIGHT_CORNER)) {
return lowerRight;
}
else if (key.equals(UPPER_LEFT_CORNER)) {
return upperLeft;
}
else if (key.equals(UPPER_RIGHT_CORNER)) {
return upperRight;
}
else {
return null;
}
}
/**
* The preferred size of a ScrollPane is the size of the insets
* plus preferred size of the viewport plus the preferred size of
* the visible headers, plus the preferred size of the scrollbars
* that will appear given the current view and the current
* scrollbar displayPolicies.
*
* @return The preferred size of the viewport and any scrollbars.
* @see ViewportLayout
* @see LayoutManager
*/
public Dimension preferredLayoutSize(Container parent)
{
Insets insets = parent.getInsets();
int prefWidth = insets.left + insets.right;
int prefHeight = insets.top + insets.bottom;
/* Note that viewport.getViewSize() is equivalent to
* viewport.getView().getPreferredSize() modulo a null
* view or a view whose size was explicitly set.
*/
Dimension extentSize = null;
Dimension viewSize = null;
Component view = null;
if (viewport != null) {
extentSize = viewport.getPreferredSize();
viewSize = viewport.getViewSize();
view = viewport.getView();
}
/* If there's a viewport add its preferredSize.
*/
if (extentSize != null) {
prefWidth += extentSize.width;
prefHeight += extentSize.height;
}
/* If there's a JScrollPane.viewportBorder, add its insets.
*/
Border viewportBorder = ((JScrollPane)parent).getViewportBorder();
if (viewportBorder != null) {
Insets vpbInsets = viewportBorder.getBorderInsets(parent);
prefWidth += vpbInsets.left + vpbInsets.right;
prefHeight += vpbInsets.top + vpbInsets.bottom;
}
/* If a header exists and it's visible, factor its
* preferred size in.
*/
if ((rowHead != null) && rowHead.isVisible()) {
prefWidth += rowHead.getPreferredSize().width;
}
if ((colHead != null) && colHead.isVisible()) {
prefHeight += colHead.getPreferredSize().height;
}
/* If a scrollbar is going to appear, factor its preferred size in.
* If the scrollbars policy is AS_NEEDED, this can be a little
* tricky:
*
* - If the view is a Scrollable then scrollableTracksViewportWidth
* and scrollableTracksViewportHeight can be used to effectively
* disable scrolling (if they're true) in their respective dimensions.
*
* - Assuming that a scrollbar hasn't been disabled by the
* previous constraint, we need to decide if the scrollbar is going
* to appear to correctly compute the JScrollPanes preferred size.
* To do this we compare the preferredSize of the viewport (the
* extentSize) to the preferredSize of the view. Although we're
* not responsible for laying out the view we'll assume that the
* JViewport will always give it its preferredSize.
*/
if ((vsb != null) && (vsbPolicy != VERTICAL_SCROLLBAR_NEVER)) {
if (vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS) {
prefWidth += vsb.getPreferredSize().width;
}
else if ((viewSize != null) && (extentSize != null)) {
boolean canScroll = true;
if (view instanceof Scrollable) {
canScroll = !((Scrollable)view).getScrollableTracksViewportHeight();
}
if (canScroll && (viewSize.height > extentSize.height)) {
prefWidth += vsb.getPreferredSize().width;
}
}
}
if ((hsb != null) && (hsbPolicy != HORIZONTAL_SCROLLBAR_NEVER)) {
if (hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) {
prefHeight += hsb.getPreferredSize().height;
}
else if ((viewSize != null) && (extentSize != null)) {
boolean canScroll = true;
if (view instanceof Scrollable) {
canScroll = !((Scrollable)view).getScrollableTracksViewportWidth();
}
if (canScroll && (viewSize.width > extentSize.width)) {
prefHeight += hsb.getPreferredSize().height;
}
}
}
return new Dimension(prefWidth, prefHeight);
}
/**
* The minimum size of a ScrollPane is the size of the insets
* plus minimum size of the viewport, plus the scrollpanes
* viewportBorder insets, plus the minimum size
* of the visible headers, plus the minimum size of the
* scrollbars whose displayPolicy isn't NEVER.
*/
public Dimension minimumLayoutSize(Container parent)
{
Insets insets = parent.getInsets();
int minWidth = insets.left + insets.right;
int minHeight = insets.top + insets.bottom;
/* If there's a viewport add its minimumSize.
*/
if (viewport != null) {
Dimension size = viewport.getMinimumSize();
minWidth += size.width;
minHeight += size.height;
}
/* If there's a JScrollPane.viewportBorder, add its insets.
*/
Border viewportBorder = ((JScrollPane)parent).getViewportBorder();
if (viewportBorder != null) {
Insets vpbInsets = viewportBorder.getBorderInsets(parent);
minWidth += vpbInsets.left + vpbInsets.right;
minHeight += vpbInsets.top + vpbInsets.bottom;
}
/* If a header exists and it's visible, factor its
* minimum size in.
*/
if ((rowHead != null) && rowHead.isVisible()) {
Dimension size = rowHead.getMinimumSize();
minWidth += size.width;
minHeight = Math.max(minHeight, size.height);
}
if ((colHead != null) && colHead.isVisible()) {
Dimension size = colHead.getMinimumSize();
minWidth = Math.max(minWidth, size.width);
minHeight += size.height;
}
/* If a scrollbar might appear, factor its minimum
* size in.
*/
if ((vsb != null) && (vsbPolicy != VERTICAL_SCROLLBAR_NEVER)) {
Dimension size = vsb.getMinimumSize();
minWidth += size.width;
minHeight = Math.max(minHeight, size.height);
}
if ((hsb != null) && (hsbPolicy != VERTICAL_SCROLLBAR_NEVER)) {
Dimension size = hsb.getMinimumSize();
minWidth = Math.max(minWidth, size.width);
minHeight += size.height;
}
return new Dimension(minWidth, minHeight);
}
/**
* Layout the scrollpane according to the following constraints:
* <ul>
* <li> The row header, if present and visible, gets its preferred
* height and the viewports width.
*
* <li> The column header, if present and visible, gets its preferred
* width and the viewports height.
*
* <li> If a vertical scrollbar is needed, i.e. if the viewports extent
* height is smaller than its view height or if the displayPolicy
* is ALWAYS, it's treated like the row header wrt it's dimensions and
* it's made visible.
*
* <li> If a horizontal scrollbar is needed it's treated like the
* column header (and see the vertical scrollbar item).
*
* <li> If the scrollpane has a non-null viewportBorder, then space
* is allocated for that.
*
* <li> The viewport gets the space available after accounting for
* the previous constraints.
*
* <li> The corner components, if provided, are aligned with the
* ends of the scrollbars and headers. If there's a vertical
* scrollbar the right corners appear, if there's a horizontal
* scrollbar the lower corners appear, a row header gets left
* corners and a column header gets upper corners.
* </ul>
*/
public void layoutContainer(Container parent)
{
Rectangle availR = new Rectangle(parent.getSize());
Insets insets = parent.getInsets();
availR.x = insets.left;
availR.y = insets.top;
availR.width -= insets.left + insets.right;
availR.height -= insets.top + insets.bottom;
/* If there's a visible column header remove the space it
* needs from the top of availR. The column header is treated
* as if it were fixed height, arbitrary width.
*/
Rectangle colHeadR = new Rectangle(0, availR.y, 0, 0);
if ((colHead != null) && (colHead.isVisible())) {
int colHeadHeight = colHead.getPreferredSize().height;
colHeadR.height = colHeadHeight;
availR.y += colHeadHeight;
availR.height -= colHeadHeight;
}
/* If there's a visible row header remove the space it needs
* from the left of availR. The row header is treated
* as if it were fixed width, arbitrary height.
*/
Rectangle rowHeadR = new Rectangle(availR.x, 0, 0, 0);
if ((rowHead != null) && (rowHead.isVisible())) {
int rowHeadWidth = rowHead.getPreferredSize().width;
rowHeadR.width = rowHeadWidth;
availR.x += rowHeadWidth;
availR.width -= rowHeadWidth;
}
/* If there's a JScrollPane.viewportBorder, remove the
* space it occupies for availR.
*/
Border viewportBorder = ((JScrollPane)parent).getViewportBorder();
Insets vpbInsets;
if (viewportBorder != null) {
vpbInsets = viewportBorder.getBorderInsets(parent);
availR.x += vpbInsets.left;
availR.y += vpbInsets.top;
availR.width -= vpbInsets.left + vpbInsets.right;
availR.height -= vpbInsets.top + vpbInsets.bottom;
}
else {
vpbInsets = new Insets(0,0,0,0);
}
colHeadR.x = availR.x;
rowHeadR.y = availR.y;
/* At this point availR is the space available for the viewport
* and scrollbars and the rowHeadR colHeadR rectangles are correct
* except for their width and height respectively. Once we're
* through computing the dimensions of these three parts we can
* go back and set the dimensions of rowHeadR.width, colHeadR.height,
* and the bounds for the corners.
*
* We'll decide about putting up scrollbars by comparing the
* viewport views preferred size with the viewports extent
* size (generally just its size). Using the preferredSize is
* reasonable because layout proceeds top down - so we expect
* the viewport to be layed out next. And it will change the
* resize the view to its preferred size or bigger. It's potentially
* bigger if the views Scrollable.getViewTracksViewport{Width,Height}
* returns true.
*/
Component view = (viewport != null) ? viewport.getView() : null;
Dimension viewSize =
(view != null) ? view.getPreferredSize()
: new Dimension(0,0);
Dimension extentSize =
(viewport != null) ? viewport.toViewCoordinates(availR.getSize())
: new Dimension(0,0);
/* If there's a vertical scrollbar and we need one, allocate
* space for it (we'll make it visible later). A vertical
* scrollbar is considered to be fixed width, arbitrary height.
*/
Rectangle vsbR = new Rectangle(0, availR.y - vpbInsets.top, 0, 0);
boolean vsbNeeded =
(vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS) ||
((viewSize.height > extentSize.height) &&
(vsbPolicy == VERTICAL_SCROLLBAR_AS_NEEDED));
if ((vsb != null) && vsbNeeded) {
int vsbWidth = vsb.getPreferredSize().width;
availR.width -= vsbWidth;
vsbR.x = availR.x + availR.width + vpbInsets.right;
vsbR.width = vsbWidth;
}
/* If there's a horizontal scrollbar and we need one, allocate
* space for it (we'll make it visible later). A horizontal
* scrollbar is considered to be fixed height, arbitrary width.
*/
Rectangle hsbR = new Rectangle(availR.x - vpbInsets.left, 0, 0, 0);
boolean hsbNeeded =
(hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) ||
((viewSize.width > extentSize.width) &&
(hsbPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED));
if ((hsb != null) && hsbNeeded) {
int hsbHeight = hsb.getPreferredSize().height;
availR.height -= hsbHeight;
hsbR.y = availR.y + availR.height + vpbInsets.bottom;
hsbR.height = hsbHeight;
/* If we added the horizontal scrollbar then we've implicitly
* reduced the vertical space available to the viewport.
* As a consequence we may have to add the vertical scrollbar,
* if that hasn't been done so already. Ofcourse we
* don't bother with any of this if the vsbPolicy is NEVER.
*/
if ((vsb != null) && !vsbNeeded && (vsbPolicy != VERTICAL_SCROLLBAR_NEVER)) {
extentSize = viewport.toViewCoordinates(availR.getSize());
vsbNeeded = viewSize.height > extentSize.height;
if (vsbNeeded) {
int vsbWidth = vsb.getPreferredSize().width;
availR.width -= vsbWidth;
vsbR.x = availR.x + availR.width + vpbInsets.right;
vsbR.width = vsbWidth;
}
}
}
/* We now have the final size of the viewport: availR.
* Now fixup the header and scrollbar widths/heights.
*/
vsbR.height = availR.height + vpbInsets.top + vpbInsets.bottom;
hsbR.width = availR.width + vpbInsets.left + vpbInsets.right;
rowHeadR.height = availR.height;
colHeadR.width = availR.width;
/* Set the bounds of all nine components. The scrollbars
* are made invisible if they're not needed.
*/
if (viewport != null) {
viewport.setBounds(availR);
}
if (rowHead != null) {
rowHead.setBounds(rowHeadR);
}
if (colHead != null) {
colHead.setBounds(colHeadR);
}
if (vsb != null) {
if (vsbNeeded) {
vsb.setVisible(true);
vsb.setBounds(vsbR);
}
else {
vsb.setVisible(false);
}
}
if (hsb != null) {
if (hsbNeeded) {
hsb.setVisible(true);
hsb.setBounds(hsbR);
}
else {
hsb.setVisible(false);
}
}
if (lowerLeft != null) {
lowerLeft.setBounds(rowHeadR.x, hsbR.y, rowHeadR.width, hsbR.height);
}
if (lowerRight != null) {
lowerRight.setBounds(vsbR.x, hsbR.y, vsbR.width, hsbR.height);
}
if (upperLeft != null) {
upperLeft.setBounds(rowHeadR.x, colHeadR.y, rowHeadR.width, colHeadR.height);
}
if (upperRight != null) {
upperRight.setBounds(vsbR.x, colHeadR.y, vsbR.width, colHeadR.height);
}
}
public Rectangle getViewportBorderBounds(JScrollPane sp)
{
Rectangle borderR = new Rectangle(sp.getSize());
Insets insets = sp.getInsets();
borderR.x = insets.left;
borderR.y = insets.top;
borderR.width -= insets.left + insets.right;
borderR.height -= insets.top + insets.bottom;
/* If there's a visible column header remove the space it
* needs from the top of borderR.
*/
if ((colHead != null) && (colHead.isVisible())) {
int colHeadHeight = colHead.getHeight();
borderR.y += colHeadHeight;
borderR.height -= colHeadHeight;
}
/* If there's a visible row header remove the space it needs
* from the left of borderR.
*/
if ((rowHead != null) && (rowHead.isVisible())) {
int rowHeadWidth = rowHead.getWidth();
borderR.x += rowHeadWidth;
borderR.width -= rowHeadWidth;
}
/* If there's a visible vertical scrollbar remove the space it needs
* from the width of borderR.
*/
if ((vsb != null) && (vsb.isVisible())) {
borderR.width -= vsb.getWidth();
}
/* If there's a visible horizontal scrollbar remove the space it needs
* from the height of borderR.
*/
if ((hsb != null) && (hsb.isVisible())) {
borderR.height -= hsb.getHeight();
}
return borderR;
}
}