1 /* 2 * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.swing.colorchooser; 27 28 import java.awt.event.FocusEvent; 29 import java.awt.event.FocusListener; 30 import java.text.ParseException; 31 import static java.util.Locale.ENGLISH; 32 import javax.swing.JFormattedTextField; 33 import javax.swing.JFormattedTextField.AbstractFormatter; 34 import javax.swing.SwingConstants; 35 import javax.swing.SwingUtilities; 36 import javax.swing.text.AttributeSet; 37 import javax.swing.text.BadLocationException; 38 import javax.swing.text.DefaultFormatterFactory; 39 import javax.swing.text.DocumentFilter; 40 41 final class ValueFormatter extends AbstractFormatter implements FocusListener, Runnable { 42 43 static void init(int length, boolean hex, JFormattedTextField text) { 44 ValueFormatter formatter = new ValueFormatter(length, hex); 45 text.setColumns(length); 46 text.setFormatterFactory(new DefaultFormatterFactory(formatter)); 47 text.setHorizontalAlignment(SwingConstants.RIGHT); 48 text.setMinimumSize(text.getPreferredSize()); 49 text.addFocusListener(formatter); 50 } 51 52 private final DocumentFilter filter = new DocumentFilter() { 53 @Override 54 public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { 55 if (isValid(fb.getDocument().getLength() - length)) { 56 fb.remove(offset, length); 57 } 58 } 59 60 @Override 61 public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet set) throws BadLocationException { 62 if (isValid(fb.getDocument().getLength() + text.length() - length) && isValid(text)) { 63 fb.replace(offset, length, text.toUpperCase(ENGLISH), set); 64 } 65 } 66 67 @Override 68 public void insertString(FilterBypass fb, int offset, String text, AttributeSet set) throws BadLocationException { 69 if (isValid(fb.getDocument().getLength() + text.length()) && isValid(text)) { 70 fb.insertString(offset, text.toUpperCase(ENGLISH), set); 71 } 72 } 73 }; 74 75 private final int length; 76 private final int radix; 77 78 private JFormattedTextField text; 79 80 ValueFormatter(int length, boolean hex) { 81 this.length = length; 82 this.radix = hex ? 16 : 10; 83 } 84 85 @Override 86 public Object stringToValue(String text) throws ParseException { 87 try { 88 return Integer.valueOf(text, this.radix); 89 } 90 catch (NumberFormatException nfe) { 91 ParseException pe = new ParseException("illegal format", 0); 92 pe.initCause(nfe); 93 throw pe; 94 } 95 } 96 97 @Override 98 public String valueToString(Object object) throws ParseException { 99 if (object instanceof Integer) { 100 if (this.radix == 10) { 101 return object.toString(); 102 } 103 int value = (Integer) object; 104 int index = this.length; 105 char[] array = new char[index]; 106 while (0 < index--) { 107 array[index] = Character.forDigit(value & 0x0F, this.radix); 108 value >>= 4; 109 } 110 return new String(array).toUpperCase(ENGLISH); 111 } 112 throw new ParseException("illegal object", 0); 113 } 114 115 @Override 116 protected DocumentFilter getDocumentFilter() { 117 return this.filter; 118 } 119 120 public void focusGained(FocusEvent event) { 121 Object source = event.getSource(); 122 if (source instanceof JFormattedTextField) { 123 this.text = (JFormattedTextField) source; 124 SwingUtilities.invokeLater(this); 125 } 126 } 127 128 public void focusLost(FocusEvent event) { 129 } 130 131 public void run() { 132 if (this.text != null) { 133 this.text.selectAll(); 134 } 135 } 136 137 private boolean isValid(int length) { 138 return (0 <= length) && (length <= this.length); 139 } 140 141 private boolean isValid(String text) { 142 int length = text.length(); 143 for (int i = 0; i < length; i++) { 144 char ch = text.charAt(i); 145 if (Character.digit(ch, this.radix) < 0) { 146 return false; 147 } 148 } 149 return true; 150 } 151 }