com.jidesoft.swing.AutoResizingTextArea Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jide-oss Show documentation
Show all versions of jide-oss Show documentation
JIDE Common Layer (Professional Swing Components)
/*
* @(#)AutosizingTextArea.java 5/11/2005
*
* Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
*/
package com.jidesoft.swing;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import java.awt.*;
/**
* An extended version of JTextArea
that automatically resizes itself vertically. This component works best
* when used in a layout that obeys preferred height of its components. For example, you can use a
* BorderLayout
and place AutoResizingTextArea
to the north or south side. Similarly, you can
* use a JideBoxLayout
and use FLEXIBLE or FIX as the constraint.
*/
public class AutoResizingTextArea extends JTextArea {
/**
* Default maximum height of the text area in rows.
*/
public static final int DEFAULT_MAX_ROWS = 20;
/**
* Default minimum height of the text area in rows.
*/
public static final int DEFAULT_MIN_ROWS = 1;
private int _maxRows;
private int _minRows;
private ResizingDocumentListener _listener;
/**
* Creates a textarea with the default minimum and maximum number of rows.
*/
public AutoResizingTextArea() {
this(DEFAULT_MIN_ROWS, DEFAULT_MAX_ROWS);
}
/**
* Creates a textarea with the specified minimum number of rows.
*
* @param minRows The minimum number of rows that this textarea can have.
*/
public AutoResizingTextArea(int minRows) {
this(minRows, DEFAULT_MAX_ROWS);
}
/**
* Creates a textarea with the specified minimum and maximum number of rows.
*
* @param minRows The minimum number of rows that this textarea can have.
* @param maxRows The maximum number of rows that this textarea can have.
*/
public AutoResizingTextArea(int minRows, int maxRows) {
super();
setMinRows(minRows);
setMaxRows(maxRows);
setRows(minRows);
}
/**
* Creates a textarea with the default minimum and maximum row count and the provided initial text. The textarea is
* sized to fit the provided text.
*
* @param text The initial text to display.
*/
public AutoResizingTextArea(String text) {
this();
setText(text);
}
/**
* Create a new AutoResizingTextArea
with a height bounded by the provided minimum and maximum row
* counts and with its width dictated by the provided column count.
*
* @param minRows The minimum number of rows that this textarea can have
* @param maxRows The maximum number of rows that this textarea can have.
* @param columns The number of columns that this textarea has.
*/
public AutoResizingTextArea(int minRows, int maxRows, int columns) {
this(minRows, maxRows);
setMinRows(minRows);
setMaxRows(maxRows);
setColumns(columns);
}
/**
* Create a new AutoResizingTextArea
with a height bounded by the provided minimum and maximum row
* counts and with its width dictated by the provided column count. The textarea is sized to fit the provided text.
*
* @param text The initial text to display in the textarea.
* @param minRows The minimum number of rows that this textarea can have
* @param maxRows The maximum number of rows that this textarea can have.
* @param columns The number of columns that this textarea has.
*
* @throws IllegalArgumentException if the rows or columns arguments are negative.
*/
public AutoResizingTextArea(String text, int minRows, int maxRows, int columns) {
this(minRows, maxRows, columns);
setText(text);
}
/**
* Create a new AutoResizingTextArea
using a Document
. The document will be set to the
* text area using {@link #setDocument(javax.swing.text.Document)}.
*
* @param doc the document.
*/
public AutoResizingTextArea(Document doc) {
this();
setDocument(doc);
}
/**
* Constructs a new AutoResizingTextArea
with the specified number of rows and columns, and the given
* model. All of the constructors feed through this constructor.
*
* @param doc the model to use, or create a default one if null
* @param text the text to be displayed, null if none
* @param minRows the minimum number of rows >= 0
* @param maxRows the maximum number of rows >= 0
* @param columns the number of columns >= 0
*
* @throws IllegalArgumentException if the rows or columns arguments are negative.
*/
public AutoResizingTextArea(Document doc, String text, int minRows, int maxRows, int columns) {
super(doc, text, minRows, columns);
setMaxRows(maxRows);
setMinRows(minRows);
}
/**
* Sets the number of visible rows. The row value will be forced to the boundaries of the range [minRows ...
* maxRows] if it is outside that range.
*
* @param rows The number of rows to show
*/
@Override
public void setRows(int rows) {
int oldRow = super.getRows();
int newRow = clipRowCount(rows);
super.setRows(newRow);
numberOfRowsUpdated(oldRow, newRow);
}
/**
* Called when the number of rows is updated. By default, it will get the parent scroll pane and call revalidate.
* Subclass can override it to customize the behavior when number of rows is updated.
*
* @param oldRow the previous row count.
* @param newRow the new row count.
*/
protected void numberOfRowsUpdated(int oldRow, int newRow) {
// look for a parent ScrollPane and revalidate its container
// otherwise revalidate the text area's container
JScrollPane scroll = getParentScrollPane();
if (scroll != null) {
Container parent = scroll.getParent();
if (parent != null && parent instanceof JComponent) {
JComponent component = (JComponent) parent;
component.revalidate();
}
}
}
/**
* Gets the maximum number of rows that will be displayed. You can set it using {@link #setMaxRows(int)} or passed
* in using constructor such as {@link #AutoResizingTextArea(int, int)}.
*
* @return the maximum number of rows that will be displayed.
*/
public int getMaxRows() {
return _maxRows;
}
/**
* Sets the maximum number of rows that will be displayed.
*
* @param maxRows The maximum number of rows.
*/
public void setMaxRows(int maxRows) {
_maxRows = maxRows;
setRows(clipRowCount(getRows()));
}
/**
* Gets the minimum number of rows that will be displayed. You can set it using {@link #setMinRows(int)} or passed
* in using constructor such as {@link #AutoResizingTextArea(int, int)}.
*
* @return the minimum number of rows that will be displayed.
*/
public int getMinRows() {
return _minRows;
}
/**
* Sets the minimum number of rows that will be displayed
*
* @param minRows The minimum number of rows.
*/
public void setMinRows(int minRows) {
_minRows = minRows;
setRows(clipRowCount(getRows()));
}
@Override
public void setDocument(Document doc) {
Document document = getDocument();
if (document != null && _listener != null) {
document.removeDocumentListener(_listener);
}
super.setDocument(doc);
if (doc != null) {
if (_listener == null) {
_listener = new ResizingDocumentListener();
}
doc.addDocumentListener(_listener);
}
updateSize();
}
/**
* Clips the given row count to fall within the range [m_minRows .. m_maxRows] (inclusive).
*
* @param rows The row count to clip.
*
* @return a row count clipped to the above range
*/
private int clipRowCount(int rows) {
int r = Math.min(_maxRows, rows); // clip to upper bounds
r = Math.max(_minRows, r); // clip to lower bounds
return r;
}
/**
* Listens to document change events and updates the row count appropriately.
*/
private class ResizingDocumentListener implements DocumentListener {
public void insertUpdate(DocumentEvent e) {
updateSize();
}
public void removeUpdate(DocumentEvent e) {
updateSize();
}
public void changedUpdate(DocumentEvent e) {
updateSize();
}
}
private int getHeight(int rows) {
Insets insets = getInsets();
return rows * getRowHeight() + insets.top + insets.bottom;
}
private void updateSize() {
// look for a parent ScrollPane and revalidate its container
// otherwise revalidate the text area's container
Container parent = getParentScrollPane();
if (parent != null && parent.getParent() instanceof JComponent) {
JComponent component = (JComponent) parent.getParent();
component.revalidate();
}
}
@Override
public Dimension getPreferredScrollableViewportSize() {
Dimension size = getPreferredSize();
if (getMinRows() != 0 && getMaxRows() != 0) {
size.height = Math.max(getHeight(getMinRows()), Math.min(getHeight(getMaxRows()), size.height));
}
return size;
}
/**
* Gets the parent scroll pane if any.
*
* @return the parent scroll pane. If not found, null will be returned.
*/
private JScrollPane getParentScrollPane() {
Component parent = getParent();
if (parent != null && parent instanceof JViewport) {
return (JScrollPane) parent.getParent();
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy