001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.gui.component; 020 021import java.awt.Color; 022import java.util.ArrayList; 023import java.util.List; 024 025/** 026 * Component to display and modify a numeric (double) value 027 * 028 * @author Yoann Le Montagner & Stephane 029 */ 030public class NumberTextField extends IcyTextField 031{ 032 /** 033 * 034 */ 035 private static final long serialVersionUID = 3043750422009529874L; 036 037 /** 038 * Listener interface 039 */ 040 public static interface ValueChangeListener 041 { 042 /** 043 * Method triggered when the numeric value in the component changes 044 */ 045 public void valueChanged(double newValue, boolean validate); 046 } 047 048 protected double value; 049 protected boolean integer; 050 protected List<ValueChangeListener> listeners; 051 052 /** 053 * Constructor 054 */ 055 public NumberTextField(boolean integer) 056 { 057 super(); 058 059 value = 0; 060 this.integer = integer; 061 listeners = new ArrayList<ValueChangeListener>(); 062 } 063 064 /** 065 * Constructor 066 */ 067 public NumberTextField() 068 { 069 this(false); 070 } 071 072 /** 073 * Return true if the range use integer number 074 */ 075 public boolean isInteger() 076 { 077 return integer; 078 } 079 080 /** 081 * Return true if the range use integer number 082 */ 083 public void setInteger(boolean integer) 084 { 085 this.integer = integer; 086 087 // force value adjustment 088 setNumericValue(value); 089 } 090 091 /** 092 * Add a new listener 093 */ 094 public void addValueListener(ValueChangeListener l) 095 { 096 listeners.add(l); 097 } 098 099 /** 100 * Remove a listener 101 */ 102 public void removeValueListener(ValueChangeListener l) 103 { 104 listeners.remove(l); 105 } 106 107 /** 108 * Retrieve the value as a double 109 */ 110 public double getNumericValue() 111 { 112 return value; 113 } 114 115 /** 116 * Set the value 117 */ 118 public void setNumericValue(double value) 119 { 120 if (integer) 121 setText(Integer.toString((int) value)); 122 else 123 setText(Double.toString(value)); 124 } 125 126 protected void valueChanged(boolean validate) 127 { 128 fireValueChangedEvent(validate); 129 } 130 131 @Override 132 protected void textChanged(boolean validate) 133 { 134 super.textChanged(validate); 135 136 double oldValue = value; 137 138 try 139 { 140 final String text = getText(); 141 value = text.isEmpty() ? 0.0 : Double.parseDouble(text); 142 // force integer 143 if (integer) 144 value = (int) value; 145 setForeground(Color.BLACK); 146 } 147 catch (NumberFormatException err) 148 { 149 setForeground(Color.RED); 150 } 151 152 if (validate) 153 valueChanged(validate); 154 else if (value != oldValue) 155 valueChanged(false); 156 } 157 158 /** 159 * Fire the value changed event 160 */ 161 private void fireValueChangedEvent(boolean validate) 162 { 163 for (ValueChangeListener l : listeners) 164 l.valueChanged(value, validate); 165 } 166}