001/** 002 * 003 */ 004package icy.gui.component.editor; 005 006import icy.gui.component.SpecialValueSpinner; 007import icy.gui.component.model.SpecialValueSpinnerModel; 008 009import java.text.DecimalFormat; 010import java.text.NumberFormat; 011import java.text.ParseException; 012 013import javax.swing.JFormattedTextField; 014import javax.swing.JSpinner.DefaultEditor; 015import javax.swing.SwingConstants; 016import javax.swing.text.DefaultFormatterFactory; 017import javax.swing.text.NumberFormatter; 018 019/** 020 * @author Stephane 021 */ 022public class SpecialValueSpinnerEditor extends DefaultEditor 023{ 024 /** 025 * 026 */ 027 private static final long serialVersionUID = -2378027484728815432L; 028 029 private static class NumberEditorFormatter extends NumberFormatter 030 { 031 /** 032 * 033 */ 034 private static final long serialVersionUID = 723313251195326099L; 035 036 private final SpecialValueSpinnerModel model; 037 038 NumberEditorFormatter(SpecialValueSpinnerModel model, NumberFormat format) 039 { 040 super(format); 041 this.model = model; 042 setValueClass(model.getValue().getClass()); 043 } 044 045 @Override 046 public void setMinimum(Comparable min) 047 { 048 model.setMinimum(min); 049 } 050 051 @Override 052 public Comparable getMinimum() 053 { 054 return model.getMinimum(); 055 } 056 057 @Override 058 public void setMaximum(Comparable max) 059 { 060 model.setMaximum(max); 061 } 062 063 @Override 064 public Comparable getMaximum() 065 { 066 return model.getMaximum(); 067 } 068 069 @Override 070 public Object stringToValue(String text) throws ParseException 071 { 072 if ((text != null) && text.equalsIgnoreCase(model.getSpecialText())) 073 return model.getSpecialValue(); 074 075 return super.stringToValue(text); 076 } 077 078 @Override 079 public String valueToString(Object value) throws ParseException 080 { 081 if ((value != null) && value.equals(model.getSpecialValue())) 082 return model.getSpecialText(); 083 084 return super.valueToString(value); 085 } 086 } 087 088 public SpecialValueSpinnerEditor(SpecialValueSpinner spinner) 089 { 090 this(spinner, (DecimalFormat) NumberFormat.getInstance(spinner.getLocale())); 091 } 092 093 public SpecialValueSpinnerEditor(SpecialValueSpinner spinner, String decimalFormatPattern) 094 { 095 this(spinner, new DecimalFormat(decimalFormatPattern)); 096 } 097 098 private SpecialValueSpinnerEditor(SpecialValueSpinner spinner, DecimalFormat format) 099 { 100 super(spinner); 101 102 if (!(spinner.getModel() instanceof SpecialValueSpinnerModel)) 103 throw new IllegalArgumentException("model not a SpecialValueSpinnerModel"); 104 105 SpecialValueSpinnerModel model = (SpecialValueSpinnerModel) spinner.getModel(); 106 NumberFormatter formatter = new NumberEditorFormatter(model, format); 107 DefaultFormatterFactory factory = new DefaultFormatterFactory(formatter); 108 JFormattedTextField ftf = getTextField(); 109 ftf.setEditable(true); 110 ftf.setFormatterFactory(factory); 111 ftf.setHorizontalAlignment(SwingConstants.RIGHT); 112 113 /* 114 * TBD - initializing the column width of the text field 115 * is imprecise and doing it here is tricky because 116 * the developer may configure the formatter later. 117 */ 118 try 119 { 120 String maxString = formatter.valueToString(model.getMinimum()); 121 String minString = formatter.valueToString(model.getMaximum()); 122 ftf.setColumns(Math.max(maxString.length(), minString.length())); 123 } 124 catch (ParseException e) 125 { 126 // TBD should throw a chained error here 127 } 128 129 } 130 131 public DecimalFormat getFormat() 132 { 133 return (DecimalFormat) ((NumberFormatter) (getTextField().getFormatter())).getFormat(); 134 } 135 136 public SpecialValueSpinnerModel getModel() 137 { 138 return (SpecialValueSpinnerModel) (getSpinner().getModel()); 139 } 140}