package org.limewire.ui.swing.components; import javax.swing.JTextField; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.PlainDocument; import org.limewire.core.api.FilePropertyKey; /** * Simplified {@link PlainDocument} filtered for text length and character type. */ public class FilteredDocument extends PlainDocument { private boolean acceptsNumeric = true; private boolean acceptsAlphabetic = true; private boolean acceptsNonAlphanumeric = true; private int maxChars = Integer.MAX_VALUE; private int minBound = Integer.MIN_VALUE; private int maxBound = Integer.MAX_VALUE; /** * Generate a document based on the validity requirements of a {@link FilePropertyKey}. * <p> NOTE: If no filtering is required then no document is added. */ public static void configure(JTextField textField, FilePropertyKey key) { if (key != null && FilePropertyKey.isLong(key)) { FilteredDocument document = new FilteredDocument(); document.setAcceptsAlphabetic(false); document.setAcceptsNumeric(true); document.setAcceptsNonAlphanumeric(false); switch (key) { case YEAR : case BITRATE : document.setMaxChars(4); break; } textField.setDocument(document); } } @Override public void insertString(int offset, String str, AttributeSet a) throws BadLocationException { boolean accept = true; if (getLength() + str.length() > maxChars) { return; } if (!acceptsAlphabetic || !acceptsNumeric || !acceptsNonAlphanumeric) { for ( byte c : str.getBytes() ) { boolean isAlphabetic = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); boolean isNumeric = c >= '0' && c <= '9'; accept &= (acceptsAlphabetic && isAlphabetic) || (acceptsNumeric && isNumeric) || (acceptsNonAlphanumeric && !isAlphabetic && !isNumeric); } if (!accept) { return; } } if (minBound != Integer.MIN_VALUE || maxBound != Integer.MAX_VALUE) { String currentText = getText(0,getLength()); String joinedString = currentText.substring(0, offset) + str + currentText.substring(offset); if (!"-".equals(joinedString)) { try { int value = Integer.parseInt(joinedString); if (value < minBound || value > maxBound) { return; } } catch (NumberFormatException e) { return; } } else if (minBound > -1 && maxBound > -1) { return; } } super.insertString(offset, str, a); } /** * If numerals can be be entered. */ public void setAcceptsNumeric(boolean accepts) { acceptsNumeric = accepts; } /** * If letters, capitals and lower cases, can be be entered. */ public void setAcceptsAlphabetic(boolean accepts) { acceptsAlphabetic = accepts; } /** * If non-alphabet-non-numerals can be entered. This includes * white space, the negative sign, and decimal points. This * should be on if requiring these. */ public void setAcceptsNonAlphanumeric(boolean accepts) { acceptsNonAlphanumeric = accepts; } /** * The maximum number of characters that can be held. */ public void setMaxChars(int max) { maxChars = max; } /** * Sets a minimum bound for number input and makes the field accept integers by defacto. * * <p> NOTE: only makes sense with values less than 2 since it will otherwise entry * will be impossible (ie. if max is 33 and min 2 can only type numbers starting with 2) */ public void setMinBound(int min) { if (min > 1) { throw new IllegalArgumentException("Using a minimum bound that is more than 1 would make things impossible to use."); } minBound = min; } /** * Sets a maximum bound and makes the field accept integers by defacto * * <p> NOTE: only makes sense with values greater than negative 2 since it will otherwise entry * will be impossible (ie. if minimum is -33 and max -11 can only type numbers starting with -1) */ public void setMaxBound(int max) { if (max < 1) { throw new IllegalArgumentException("Using a maximum bound that is less than -1 would make things impossible to use."); } maxBound = max; } }