001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.tagging.ac; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import javax.swing.text.AttributeSet; 007import javax.swing.text.BadLocationException; 008import javax.swing.text.DocumentFilter; 009import javax.swing.text.StyleConstants; 010 011/** 012 * A {@link DocumentFilter} to limit the text length in the editor. 013 * @since 18221 014 */ 015public class MaxLengthDocumentFilter extends DocumentFilter { 016 /** the document will not accept text longer than this. -1 to disable */ 017 private int maxLength = -1; 018 private static final String DIFFERENT = tr("<different>"); 019 020 /** 021 * Sets the maximum text length. 022 * 023 * @param length the maximum no. of charactes allowed in this document. -1 to disable 024 */ 025 public void setMaxLength(int length) { 026 maxLength = length; 027 } 028 029 @Override 030 public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) 031 throws BadLocationException { 032 if (mustInsertOrReplace(fb, 0, string, attr)) { 033 super.insertString(fb, offset, string, attr); 034 } 035 } 036 037 @Override 038 public void replace(FilterBypass fb, int offset, int length, String string, AttributeSet attr) 039 throws BadLocationException { 040 if (mustInsertOrReplace(fb, length, string, attr)) { 041 super.replace(fb, offset, length, string, attr); 042 } 043 } 044 045 private boolean mustInsertOrReplace(FilterBypass fb, int length, String string, AttributeSet attr) { 046 int newLen = fb.getDocument().getLength() - length + ((string == null) ? 0 : string.length()); 047 return (maxLength == -1 || newLen <= maxLength || DIFFERENT.equals(string) || 048 // allow longer text while composing characters or it will be hard to compose 049 // the last characters before the limit 050 ((attr != null) && attr.isDefined(StyleConstants.ComposedTextAttribute))); 051 } 052}