Como limitar as linhas e colunas de um JTextArea?

2015/08/05

Este exemplo visa mostrar como implementar um DocumentFilter para limitar a quantidade de linhas e colunas em um componente JTextArea.

Perceba que na classe abaixo fazemos o seguinte:

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.AbstractDocument;

public class Exemplo {

    public static void main(String[] args) {
        try {
            // Primeiro criamos uma instância de MaximumSizeFilter
            int linhas = 10;
            int colunas = 80;
            MaximumSizeFilter filter = new MaximumSizeFilter(linhas, colunas);

            // Em seguida definimos o MaximumSizeFilter como sendo o DocumentFilter do AbstractDocument
            JTextArea textArea = new JTextArea();
            AbstractDocument document = (AbstractDocument) textArea.getDocument();
            document.setDocumentFilter(filter);

            JFrame frame = new JFrame("Exemplo");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(BorderLayout.CENTER, new JScrollPane(textArea));
            frame.setSize(640, 480);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}

Abaixo está o código fonte do MaximumSizeFilter:

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;
import javax.swing.text.Element;

public final class MaximumSizeFilter extends DocumentFilter {

    private final int maxRows;
    private final int maxCols;

    public MaximumSizeFilter(int maxRows, int maxCols) {
        this.maxRows = maxRows;
        this.maxCols = maxCols;
    }

    public void insertString(DocumentFilter.FilterBypass fb, int offset, String str, AttributeSet attr) throws BadLocationException {
        replace(fb, offset, 0, str, attr);
    }

    public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String str, AttributeSet attrs) throws BadLocationException {
        Document doc = fb.getDocument();
        fb.replace(offset, length, str, attrs);
        Element root = doc.getDefaultRootElement();
        for (int index = 0; index < root.getElementCount(); index++) {
            Element e = root.getElement(index);
            int lineLength = e.getEndOffset() - e.getStartOffset() - 1;
            if (lineLength > this.maxCols) {
                fb.remove(e.getStartOffset() + this.maxCols, lineLength - this.maxCols);
            }
        }
        if (root.getElementCount() > this.maxRows) {
            int offsetInvalidRow = root.getElement(this.maxRows).getStartOffset();
            fb.remove(offsetInvalidRow - 1, root.getEndOffset() - offsetInvalidRow);
        }
    }
}

Por hoje é só pessoal!