/* * @(#)JLifeFormattedTextField.java * * Copyright (c) 2009-2010 The authors and contributors of JHotDraw. * You may not use, copy or modify this file, except in compliance with the * accompanying license terms. */ package org.jhotdraw.gui; import edu.umd.cs.findbugs.annotations.Nullable; import java.text.*; import java.util.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; /** * A JFormattedTextField which updates its value while the user is editing * the field. * * @author Werner Randelshofer * @version $Id$ */ public class JLifeFormattedTextField extends JFormattedTextField { private static final long serialVersionUID = 1L; /** * Last valid value. */ @Nullable private Object value; /** The DocumentHandler listens for document changes while the user is * editing the field. */ private class DocumentHandler implements DocumentListener { @Override public void insertUpdate(DocumentEvent e) { updateValue(); } @Override public void removeUpdate(DocumentEvent e) { updateValue(); } @Override public void changedUpdate(DocumentEvent e) { updateValue(); } } /** The DocumentHandler handles document changes while the user is * editing the field. */ private DocumentHandler documentHandler; /** * This variable is used to prevent endless update loops. * We increase its value on each entry in one of the update methods * and decrease it on each exit. */ private int updatingDepth; /** Creates new instance. */ public JLifeFormattedTextField() { } @Override public void setDocument(Document newValue) { Document oldValue = getDocument(); super.setDocument(newValue); if (documentHandler == null) { documentHandler = new DocumentHandler(); } if (oldValue != null) { oldValue.removeDocumentListener(documentHandler); } if (newValue != null) { newValue.addDocumentListener(documentHandler); } updateValue(); } @Override public void setValue(Object newValue) { Object oldValue = this.value; if (oldValue != null && newValue != null && oldValue.equals(newValue)) { return; } if (newValue != null && getFormatterFactory() == null) { setFormatterFactory(getDefaultFormatterFactory(newValue)); } this.value = newValue; firePropertyChange("value", oldValue, newValue); updateText(); } @Override public Object getValue() { return value; } /** * Updates the value from the text of the field. */ protected void updateValue() { if (updatingDepth++ == 0) { if (getFormatter() != null) { try { Object newValue = getFormatter().stringToValue(getText()); setValue(newValue); } catch (ParseException ex) { //ex.printStackTrace();// do nothing } } } updatingDepth--; } /** * Updates the text of the field from the value. */ protected void updateText() { if (updatingDepth++ == 0) { if (getFormatter() != null) { try { String newText = getFormatter().valueToString(getValue()); setText(newText); if (!isFocusOwner()) { // This is like selectAll(), but we set the // cursor at the start of the field, because // the start of the field contains the most // significant part of the field content. setCaretPosition(getDocument().getLength()); moveCaretPosition(0); } } catch (ParseException ex) { //ex.printStackTrace(); do nothing } } } updatingDepth--; } /** * Returns an AbstractFormatterFactory suitable for the passed in * Object type. */ private AbstractFormatterFactory getDefaultFormatterFactory(Object type) { if (type instanceof DateFormat) { return new DefaultFormatterFactory(new DateFormatter((DateFormat) type)); } if (type instanceof NumberFormat) { return new DefaultFormatterFactory(new NumberFormatter( (NumberFormat) type)); } if (type instanceof Format) { return new DefaultFormatterFactory(new InternationalFormatter( (Format) type)); } if (type instanceof Date) { return new DefaultFormatterFactory(new DateFormatter()); } if (type instanceof Number) { AbstractFormatter displayFormatter = new NumberFormatter(); ((NumberFormatter) displayFormatter).setValueClass(type.getClass()); AbstractFormatter editFormatter = new NumberFormatter( new DecimalFormat("#.#")); ((NumberFormatter) editFormatter).setValueClass(type.getClass()); return new DefaultFormatterFactory(displayFormatter, displayFormatter, editFormatter); } return new DefaultFormatterFactory(new DefaultFormatter()); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { }// </editor-fold>//GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables // End of variables declaration//GEN-END:variables }