
com.jidesoft.swing.JideScrollPane Maven / Gradle / Ivy
/*
* @(#)JideScrollPane.java
*
* Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
*/
package com.jidesoft.swing;
import javax.swing.*;
import java.awt.*;
/**
* JideScrollPane
is an enhanced version of JScrollPane
. In
* JScrollPane
, you can have rowHeader and columnHeader. However you can't
* have rowFooter and columnFooter. However rowFooter and columnFooter are very useful in
* table. For example they can be used to display "total" or "summary" type of information.
*
* Several methods related to rowFooter and columnFooter are added such as
* {@link #setRowFooter(javax.swing.JViewport)}, and {@link #setColumnFooter(javax.swing.JViewport)}
* which will set the viewport to rowFooter and columnFooter area respectively. The usage
* of those methods are exactly the same as {@link JScrollPane#setRowHeader(javax.swing.JViewport)}.
*
* To fully leverage the power of JideScrollPane, we also create
* a class called TableScrollPane
which
* is part of JIDE Grids package. It will allow you to
* easily create table with row header, row footer and column footer.
* JideScrollPane
also provides support for scrollbar corners. You can set them using {@link #setScrollBarCorner(String,java.awt.Component)}.
* Available key for scroll bar corner is defined at {@link JideScrollPaneConstants} which can be access from JideScrollPane
.
*
* Credit: This implementation of scroll bar corner is based on work from Santhosh Kumar - [email protected].
*/
public class JideScrollPane extends JScrollPane implements JideScrollPaneConstants {
/**
* The row footer child. Default is null
.
*
* @see #setRowFooter
*/
protected JViewport _rowFooter;
/**
* The column footer child. Default is null
.
*
* @see #setColumnFooter
*/
protected JViewport _columnFooter;
/**
* The component to the left of horizontal scroll bar.
*/
protected Component _hLeft;
/**
* The component to the right of horizontal scroll bar.
*/
protected Component _hRight;
/**
* The component to the top of vertical scroll bar.
*/
protected Component _vTop;
/**
* The component to the bottom of vertical scroll bar.
*/
protected Component _vBottom;
private boolean _horizontalScrollBarCoversWholeWidth;
private boolean _verticalScrollBarCoversWholeHeight;
public static final String PROPERTY_HORIZONTAL_SCROLL_BAR_COVERS_WHOLE_WIDTH = "horizontalScrollBarCoversWholeWidth";
public static final String PROPERTY_VERTICAL_SCROLL_BAR_COVERS_WHOLE_HEIGHT = "verticalScrollBarCoversWholeHeight";
/**
* Creates a JideScrollPane
that displays the view
* component in a viewport
* whose view position can be controlled with a pair of scrollbars.
* The scrollbar policies specify when the scrollbars are displayed,
* For example, if vsbPolicy
is
* VERTICAL_SCROLLBAR_AS_NEEDED
* then the vertical scrollbar only appears if the view doesn't fit
* vertically. The available policy settings are listed at
* {@link #setVerticalScrollBarPolicy} and
* {@link #setHorizontalScrollBarPolicy}.
*
* @param view the component to display in the scrollpanes viewport
* @param vsbPolicy an integer that specifies the vertical
* scrollbar policy
* @param hsbPolicy an integer that specifies the horizontal
* scrollbar policy
* @see #setViewportView
*/
public JideScrollPane(Component view, int vsbPolicy, int hsbPolicy) {
setLayout(new JideScrollPaneLayout.UIResource());
setVerticalScrollBarPolicy(vsbPolicy);
setHorizontalScrollBarPolicy(hsbPolicy);
setViewport(createViewport());
setVerticalScrollBar(createVerticalScrollBar());
setHorizontalScrollBar(createHorizontalScrollBar());
if (null != view) {
setViewportView(view);
}
setOpaque(true);
updateUI();
if (!getComponentOrientation().isLeftToRight()) {
viewport.setViewPosition(new Point(Integer.MAX_VALUE, 0));
}
}
/**
* Creates a JideScrollPane
that displays the
* contents of the specified
* component, where both horizontal and vertical scrollbars appear
* whenever the component's contents are larger than the view.
*
* @param view the component to display in the scrollpane's viewport
* @see #setViewportView
*/
public JideScrollPane(Component view) {
this(view, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
/**
* Creates an empty (no viewport view) JideScrollPane
* with specified
* scrollbar policies. The available policy settings are listed at
* {@link #setVerticalScrollBarPolicy} and
* {@link #setHorizontalScrollBarPolicy}.
*
* @param vsbPolicy an integer that specifies the vertical
* scrollbar policy
* @param hsbPolicy an integer that specifies the horizontal
* scrollbar policy
* @see #setViewportView
*/
public JideScrollPane(int vsbPolicy, int hsbPolicy) {
this(null, vsbPolicy, hsbPolicy);
}
/**
* Creates an empty (no viewport view) JideScrollPane
* where both horizontal and vertical scrollbars appear when needed.
*/
public JideScrollPane() {
this(null, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
/**
* Returns the row footer.
*
* @return the rowFooter
property
* @see #setRowFooter
*/
public JViewport getRowFooter() {
return _rowFooter;
}
/**
* Removes the old rowFooter, if it exists. If the new rowFooter
* isn't null
, syncs the y coordinate of its
* viewPosition with
* the viewport (if there is one) and then adds it to the scrollpane.
*
* @param rowFooter the new row footer to be used; if null
* the old row footer is still removed and the new rowFooter
* is set to null
* @see #getRowFooter
* @see #setRowFooterView
*/
public void setRowFooter(JViewport rowFooter) {
JViewport old = getRowFooter();
_rowFooter = rowFooter;
if (null != rowFooter) {
add(rowFooter, ROW_FOOTER);
}
else if (null != old) {
remove(old);
}
firePropertyChange("rowFooter", old, rowFooter);
revalidate();
repaint();
JideSwingUtilities.synchronizeView(rowFooter, getViewport(), SwingConstants.VERTICAL);
}
/**
* Overwride setRowHeader method in JScrollPane and synchronize the view with the main viewport.
* Swing tried to implement this feature but it will break if the view position changes starts from rowHeader.
*
* @param rowHeader the new row header
*/
@Override
public void setRowHeader(JViewport rowHeader) {
super.setRowHeader(rowHeader);
JideSwingUtilities.synchronizeView(rowHeader, getViewport(), SwingConstants.VERTICAL);
}
/**
* Creates a row-footer viewport if necessary, sets
* its view and then adds the row-footer viewport
* to the scrollpane. For example:
*
* JScrollPane scrollpane = new JideScrollPane();
* scrollpane.setViewportView(myBigComponentToScroll);
* scrollpane.setRowFooterView(myBigComponentsRowFooter);
*
*
* @param view the component to display as the row footer
* @see #setRowFooter
* @see JViewport#setView
*/
public void setRowFooterView(Component view) {
if (null == getRowFooter()) {
setRowFooter(createViewport());
}
getRowFooter().setView(view);
}
/**
* Returns the column footer.
*
* @return the columnFooter
property
* @see #setColumnFooter
*/
public JViewport getColumnFooter() {
return _columnFooter;
}
/**
* Removes the old columnFooter, if it exists. If the new columnFooter
* isn't null
, sync the x coordinate of the its viewPosition
* with the viewport (if there is one) and then add it to the scrollpane.
*
* @param columnFooter the new column footer to be used; if null
* the old column footer is still removed and the new columnFooter
* is set to null
* @see #getColumnFooter
* @see #setColumnFooterView
*/
public void setColumnFooter(JViewport columnFooter) {
JViewport old = getColumnFooter();
_columnFooter = columnFooter;
if (null != columnFooter) {
add(columnFooter, COLUMN_FOOTER);
}
else if (null != old) {
remove(old);
}
firePropertyChange("columnFooter", old, columnFooter);
revalidate();
repaint();
JideSwingUtilities.synchronizeView(_columnFooter, getViewport(), SwingConstants.HORIZONTAL);
}
/**
* Overrides to make column header viewport synchonizing with the main viewport.
*
* @param columnHeader
*/
@Override
public void setColumnHeader(JViewport columnHeader) {
super.setColumnHeader(columnHeader);
JideSwingUtilities.synchronizeView(this.columnHeader, getViewport(), SwingConstants.HORIZONTAL);
}
/**
* Creates a column-footer viewport if necessary, sets
* its view, and then adds the column-footer viewport
* to the scrollpane. For example:
*
* JScrollPane scrollpane = new JideScrollPane();
* scrollpane.setViewportView(myBigComponentToScroll);
* scrollpane.setColumnFooterView(myBigComponentsColumnFooter);
*
*
* @param view the component to display as the column footer
* @see #setColumnFooter
* @see JViewport#setView
*/
public void setColumnFooterView(Component view) {
if (null == getColumnFooter()) {
setColumnFooter(createViewport());
}
getColumnFooter().setView(view);
}
/**
* Returns the component at the specified scroll bar corner. The
* key
value specifying the corner is one of:
*
* - {@link JideScrollPane#HORIZONTAL_LEFT}
*
- {@link JideScrollPane#HORIZONTAL_RIGHT}
*
- {@link JideScrollPane#VERTICAL_TOP}
*
- {@link JideScrollPane#VERTICAL_BOTTOM}
*
- {@link JideScrollPane#HORIZONTAL_LEADING}
*
- {@link JideScrollPane#HORIZONTAL_TRAILING}
*
*
* @param key one of the values as shown above
* @return one of the components listed below or null
* if key
is invalid:
*
* - lowerLeft
*
- lowerRight
*
- upperLeft
*
- upperRight
*
* @see #setCorner
*/
public Component getScrollBarCorner(String key) {
boolean isLeftToRight = getComponentOrientation().isLeftToRight();
if (key.equals(HORIZONTAL_LEADING)) {
key = isLeftToRight ? HORIZONTAL_LEFT : HORIZONTAL_RIGHT;
}
else if (key.equals(HORIZONTAL_TRAILING)) {
key = isLeftToRight ? HORIZONTAL_RIGHT : HORIZONTAL_LEFT;
}
if (key.equals(HORIZONTAL_LEFT)) {
return _hLeft;
}
else if (key.equals(HORIZONTAL_RIGHT)) {
return _hRight;
}
else if (key.equals(VERTICAL_BOTTOM)) {
return _vBottom;
}
else if (key.equals(VERTICAL_TOP)) {
return _vTop;
}
else {
return null;
}
}
/**
* Adds a child that will appear in one of the scroll bars
* corners. Scroll bar will make room to show the corner component.
* Legal values for
* the key are:
*
* - {@link JideScrollPane#HORIZONTAL_LEFT}
*
- {@link JideScrollPane#HORIZONTAL_RIGHT}
*
- {@link JideScrollPane#VERTICAL_TOP}
*
- {@link JideScrollPane#VERTICAL_BOTTOM}
*
- {@link JideScrollPane#HORIZONTAL_LEADING}
*
- {@link JideScrollPane#HORIZONTAL_TRAILING}
*
*
* Although "corner" doesn't match any beans property
* signature, PropertyChange
events are generated with the
* property name set to the corner key.
*
* @param key identifies which corner the component will appear in
* @param corner one of the following components:
*
* - lowerLeft
*
- lowerRight
*
- upperLeft
*
- upperRight
*
* @throws IllegalArgumentException if corner key is invalid
*/
public void setScrollBarCorner(String key, Component corner) {
Component old;
boolean isLeftToRight = getComponentOrientation().isLeftToRight();
if (key.equals(HORIZONTAL_LEADING)) {
key = isLeftToRight ? HORIZONTAL_LEFT : HORIZONTAL_RIGHT;
}
else if (key.equals(HORIZONTAL_TRAILING)) {
key = isLeftToRight ? HORIZONTAL_RIGHT : HORIZONTAL_LEFT;
}
if (key.equals(HORIZONTAL_LEFT)) {
old = _hLeft;
_hLeft = corner;
}
else if (key.equals(HORIZONTAL_RIGHT)) {
old = _hRight;
_hRight = corner;
}
else if (key.equals(VERTICAL_TOP)) {
old = _vTop;
_vTop = corner;
}
else if (key.equals(VERTICAL_BOTTOM)) {
old = _vBottom;
_vBottom = corner;
}
else {
throw new IllegalArgumentException("invalid scroll bar corner key");
}
if (null != old) {
remove(old);
}
if (null != corner) {
add(corner, key);
}
firePropertyChange(key, old, corner);
revalidate();
repaint();
}
@Override
public void updateUI() {
super.updateUI();
LookAndFeel.installBorder(this, "JideScrollPane.border");
}
public boolean isVerticalScrollBarCoversWholeHeight() {
return _verticalScrollBarCoversWholeHeight;
}
public boolean isHorizontalScrollBarCoversWholeWidth() {
return _horizontalScrollBarCoversWholeWidth;
}
public void setHorizontalScrollBarCoversWholeWidth(boolean horizontalScrollBarCoversWholeWidth) {
boolean old = _horizontalScrollBarCoversWholeWidth;
if (old != horizontalScrollBarCoversWholeWidth) {
_horizontalScrollBarCoversWholeWidth = horizontalScrollBarCoversWholeWidth;
firePropertyChange(PROPERTY_HORIZONTAL_SCROLL_BAR_COVERS_WHOLE_WIDTH, old, _horizontalScrollBarCoversWholeWidth);
invalidate();
doLayout();
if (getHorizontalScrollBar() != null) {
getHorizontalScrollBar().doLayout();
}
}
}
public void setVerticalScrollBarCoversWholeHeight(boolean verticalScrollBarCoversWholeHeight) {
boolean old = _verticalScrollBarCoversWholeHeight;
if (old != verticalScrollBarCoversWholeHeight) {
_verticalScrollBarCoversWholeHeight = verticalScrollBarCoversWholeHeight;
firePropertyChange(PROPERTY_VERTICAL_SCROLL_BAR_COVERS_WHOLE_HEIGHT, old, _verticalScrollBarCoversWholeHeight);
invalidate();
doLayout();
if (getVerticalScrollBar() != null) {
getVerticalScrollBar().doLayout();
}
}
}
@Override
protected JViewport createViewport() {
return new JViewport() {
@Override
public Dimension getViewSize() {
Dimension viewSize = super.getViewSize();
if (getView() == JideScrollPane.this.getViewport().getView()) {
if (rowHeader != null) {
Dimension headerSize = rowHeader.getViewSize();
if (viewSize.height < headerSize.height) {
viewSize.height = headerSize.height;
}
}
else if (columnHeader != null) {
Dimension headerSize = columnHeader.getViewSize();
if (viewSize.width < headerSize.width) {
viewSize.width = headerSize.width;
}
}
}
return viewSize;
}
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy