![JAR search and dependency download from the Maven repository](/logo.png)
org.appdapter.gui.swing.JAutoResizingTextArea Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.appdapter.lib.gui Show documentation
Show all versions of org.appdapter.lib.gui Show documentation
Appdapter Maven project including Java and Scala, produces jar, not bundle. Excludes concrete SLF4J binding.
The newest version!
package org.appdapter.gui.swing;
/*
* @(#)AutosizingTextArea.java 5/11/2005
*
* Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
*/
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Insets;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JViewport;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.PlainDocument;
/**
* 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 JAutoResizingTextArea
to the north or south side. Similarly, you can
* use a JideBoxLayout
and use FLEXIBLE or FIX as the constraint.
*/
public class JAutoResizingTextArea extends JEditorPane {
int rows = 24, columns = 80;
boolean linewrap;
public void superSetRows(int newRows) {
rows = newRows;
//JTextArea super.setRows(newRows);
}
public void setLineWrap(boolean wrap) {
linewrap = wrap;
//JTextArea super.setLineWrap(wrap);
}
public void setColumns(int columns) {
this.columns = columns;
//JTextArea super.setColumns(columns);
}
public int getRows() {
return rows;
//JTextArea return super.getRows();
}
/**
* Determines the number of lines contained in the area.
*
* @return the number of lines > 0
*/
public int getLineCount() {
Element map = getDocument().getDefaultRootElement();
return map.getElementCount();
}
public void replaceRange(String str, int start, int end) {
if (end < start) {
throw new IllegalArgumentException("end before start");
}
Document doc = getDocument();
if (doc != null) {
try {
if (doc instanceof AbstractDocument) {
((AbstractDocument) doc).replace(start, end - start, str, null);
} else {
doc.remove(start, end - start);
doc.insertString(start, str, null);
}
} catch (BadLocationException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
}
public void setTabSize(int size) {
Document doc = getDocument();
if (doc != null) {
int old = getTabSize();
doc.putProperty(PlainDocument.tabSizeAttribute, new Integer(size));
firePropertyChange("tabSize", old, size);
}
}
public int getTabSize() {
int size = 8;
Document doc = getDocument();
if (doc != null) {
Integer i = (Integer) doc.getProperty(PlainDocument.tabSizeAttribute);
if (i != null) {
size = i.intValue();
}
}
return size;
}
/**
* Determines the offset of the start of the given line.
*
* @param line the line number to translate >= 0
* @return the offset >= 0
* @exception BadLocationException thrown if the line is
* less than zero or greater or equal to the number of
* lines contained in the document (as reported by
* getLineCount).
*/
public int getLineStartOffset(int line) throws BadLocationException {
int lineCount = getLineCount();
if (line < 0) {
throw new BadLocationException("Negative line", -1);
} else if (line >= lineCount) {
throw new BadLocationException("No such line", getDocument().getLength() + 1);
} else {
Element map = getDocument().getDefaultRootElement();
Element lineElem = map.getElement(line);
return lineElem.getStartOffset();
}
}
public int getLineOfOffset(int offset) throws BadLocationException {
Document doc = getDocument();
if (offset < 0) {
throw new BadLocationException("Can't translate offset to line", -1);
} else if (offset > doc.getLength()) {
throw new BadLocationException("Can't translate offset to line", doc.getLength() + 1);
} else {
Element map = getDocument().getDefaultRootElement();
return map.getElementIndex(offset);
}
}
public void insert(String str, int pos) {
Document doc = getDocument();
if (doc != null) {
try {
doc.insertString(pos, str, null);
} catch (BadLocationException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
}
public int getRowHeight() {
FontMetrics metrics = getFontMetrics(getFont());
return metrics.getHeight();
}
/**
* 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 JAutoResizingTextArea() {
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 JAutoResizingTextArea(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 JAutoResizingTextArea(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 JAutoResizingTextArea(String text) {
this();
setText(text);
}
/**
* Create a new JAutoResizingTextArea
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 JAutoResizingTextArea(int minRows, int maxRows, int columns) {
this(minRows, maxRows);
setMinRows(minRows);
setMaxRows(maxRows);
setColumns(columns);
}
/**
* Create a new JAutoResizingTextArea
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 JAutoResizingTextArea(String text, int minRows, int maxRows, int columns) {
this(minRows, maxRows, columns);
setText(text);
}
/**
* Create a new JAutoResizingTextArea
using a Document
. The document will be set to the
* text area using {@link #setDocument(javax.swing.text.Document)}.
*
* @param doc the document.
*/
public JAutoResizingTextArea(Document doc) {
this();
setDocument(doc);
}
/**
* Constructs a new JAutoResizingTextArea
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 JAutoResizingTextArea(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
*/
public void setRows(int rows) {
int oldRow = getRows();
int newRow = clipRowCount(rows);
superSetRows(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 #JAutoResizingTextArea(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 #JAutoResizingTextArea(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