Revision 272

View differences:

trunk/org.gvsig.app.document.layout2.app/org.gvsig.app.document.layout2.app.mainplugin/src/main/java/org/gvsig/app/project/documents/layout/fframes/gui/numberFormat/CharComboBox.java
1
package org.gvsig.app.project.documents.layout.fframes.gui.numberFormat;
2

  
3
import java.awt.event.FocusEvent;
4
import java.awt.event.FocusListener;
5
import java.util.ArrayList;
6

  
7
import javax.swing.JComboBox;
8

  
9
import org.gvsig.i18n.Messages;
10

  
11
/**
12
 * This is is a customized JComboBox used to select a single character.
13
 * It has the following properties:
14
 * <ul>
15
 * <li>it is editable</li>
16
 * <li>only allows a single char (if more chars are introduced, the string
17
 * is trimmed to the first character</li>
18
 * <li>optionally, it can show a special item (NoneItem) that represents that no
19
 * character wants to be selected.</li></ul>
20
 * 
21
 * @author Cesar Martinez Izquierdo
22
 *
23
 */
24
public class CharComboBox extends JComboBox {
25
	private static final long serialVersionUID = 2194202669931887456L;
26
	/**
27
	 * This item represents that no item is selected
28
	 */
29
	private String noneItem = Messages.getText("None");
30
	
31
	public CharComboBox(String[] items, boolean showNoneItem) {
32
		super();
33
		this.setEditable(true);
34
		for (int i=0; i<items.length; i++) {
35
			String item = items[i];
36
			if (item!=null && item.length()>0) {
37
				this.addItem(new String(item.substring(0, 1)));
38
			}
39
		}
40
		if (showNoneItem) {
41
			this.addItem(noneItem);
42
		}
43
		this.addFocusListener(new FocusListener() {
44

  
45
			public void focusGained(FocusEvent e) {	
46
			}
47

  
48
			public void focusLost(FocusEvent e) {
49
				String item = getSelectedItem();
50
				if (item!=null) {
51
					setSelectedItem(item);
52
				}
53
			}
54
			
55
		});
56
	}
57
	
58
	public CharComboBox() {
59
		this(new String[]{" "}, true);
60
	}
61
	
62
	/**
63
	 * Returns the selected char, or null if the NoneItem is
64
	 * selected.
65
	 * @see javax.swing.JComboBox#getSelectedItem()
66
	 */
67
	public String getSelectedItem() {
68
		String item = (String) super.getSelectedItem();
69
		if (item!=null && item!=noneItem) {
70
			if (item.length()>0) {
71
				return item.substring(0, 1);
72
			}
73
			else {
74
				return " ";
75
			}
76
		}
77
		else {
78
			return null;
79
		}
80
	}
81
	
82
	// Ensure all the added items are Strings
83
	public void addItem(Object obj) {
84
		super.addItem(String.valueOf(obj));
85
	}
86
	
87
	/**
88
	 * Sets the text to show as the NoneItem. The text has to be
89
	 * provided in its localized form (if translations are in use).
90
	 * 
91
	 * @param text The localized text to show as the NoneItem
92
	 */
93
	public void setNoneItemText(String text) {
94
		noneItem = text;
95
	}
96
	
97
	
98
	
99
	
100
	
101
	
102

  
103
}
trunk/org.gvsig.app.document.layout2.app/org.gvsig.app.document.layout2.app.mainplugin/src/main/java/org/gvsig/app/project/documents/layout/fframes/gui/numberFormat/DecimalFormatPanel.java
1
package org.gvsig.app.project.documents.layout.fframes.gui.numberFormat;
2

  
3
import java.awt.BorderLayout;
4
import java.awt.event.ActionEvent;
5
import java.awt.event.ActionListener;
6
import java.text.DecimalFormat;
7
import java.text.DecimalFormatSymbols;
8

  
9
import javax.swing.JComboBox;
10
import javax.swing.JFrame;
11
import javax.swing.JLabel;
12

  
13
import org.gvsig.gui.beans.swing.GridBagLayoutPanel;
14
import org.gvsig.gui.beans.swing.JIncrementalNumberField;
15
import org.gvsig.gui.beans.swing.ValidatingTextField;
16
import org.gvsig.gui.beans.swing.ValidatingTextField.Cleaner;
17
import org.gvsig.gui.beans.swing.ValidatingTextField.Validator;
18
import org.gvsig.i18n.Messages;
19

  
20

  
21
/**
22
 * A panel to select the format for a decimal number. The following options are
23
 * offered:
24
 * <ul>
25
 * <li>The decimal separator character</li>
26
 * <li>The thousands separator character</li>
27
 * <li>The number of decimal digits. Note that this component forces the
28
 * maximum and minimum number of decimal digits (as defined in {@link DecimalFormat})
29
 * to be always equal.</li>
30
 * </ul>
31
 * 
32
 * @author Cesar Martinez Izquierdo
33
 */
34
public class DecimalFormatPanel extends GridBagLayoutPanel {
35
	private static final long serialVersionUID = 1L;
36
	public static final String INTEGER_BASE_PATTERN = "0";
37
	public static final String INTEGER_GROUPED_BASE_PATTERN = "#,###,###,###,###,###,##0";
38
	public static final String DECIMAL_BASE_PATTERN = "#0.";
39
	public static final String DECIMAL_GROUPED_BASE_PATTERN = "#,###,###,###,###,###,##0.";
40
	private DecimalFormat format;
41
	private CharComboBox cbDecimalSep = null;
42
	private CharComboBox cbThousandsSep = null;
43
	private JIncrementalNumberField tfDecimalDigits = null;
44
	private JLabel lbResult = null;
45
	private double testNumber = 123456789.00;
46
	private static final DecimalFormatSymbols defaultLocaleSymbols = DecimalFormatSymbols.getInstance();
47
	
48
	/**
49
	 * Creates and initializes the panel using the default format
50
	 *  for the current locale
51
	 */
52
	public DecimalFormatPanel() {
53
		this(new DecimalFormat());
54
	}
55
	
56
	/**
57
	 * Creates and initializes the panel using the provided
58
	 * DecimalFormat 
59
	 */
60
	public DecimalFormatPanel(DecimalFormat format) {
61
		super();
62
		initComponents();
63
		setFormat(format);
64
	}
65
	
66
	/**
67
	 * Creates and initializes the panel using the provided parameters
68
	 * 
69
	 * @param decimalSeparator The character used to separate the decimal part
70
	 * @param thousandsSeparator The character used to group thousands
71
	 * @param decimalDigits The number of decimal digits to show
72
	 * @param basePattern A base pattern used to create the DecimalFormat.
73
	 * Usually, one of {@link #INTEGER_BASE_PATTERN},
74
	 * {@link #INTEGER_GROUPED_BASE_PATTERN}, {@link #DECIMAL_BASE_PATTERN}
75
	 * or {@link #DECIMAL_GROUPED_BASE_PATTERN}.
76
	 * Any decimal digits in the pattern will be ignored (as they will be
77
	 * included depending on the <code>decimalDigits</code> parameter). The
78
	 * behavior of the component is undefined if a wrong pattern is provided
79
	 * 
80
	 * @see DecimalFormat
81
	 */
82
	public DecimalFormatPanel(char decimalSeparator, char thousandsSeparator, int decimalDigits, String basePattern) {
83
		super();
84
		initComponents();
85
		DecimalFormatSymbols sym = new DecimalFormatSymbols();
86
		sym.setDecimalSeparator(decimalSeparator);
87
		sym.setGroupingSeparator(thousandsSeparator);
88
		String pattern = getPattern(basePattern, decimalDigits);
89
		DecimalFormat f = new DecimalFormat(pattern, sym);
90
		setFormat(f);
91
	}
92
	
93
	protected void initComponents() {
94
		this.addComponent(Messages.getText("Decimal_separator"), getCbDecimalSep());
95
		this.addComponent(Messages.getText("Thousands_separator"), getCbThousandsSep());
96
		this.addComponent(Messages.getText("Decimal_digits"), getTfDecimalDigits());
97
		this.addComponent(Messages.getText("Result"), getLbTestResult());
98
		
99
	}
100
	
101
	private String getPattern(String basePattern, int decimalDigits) {
102
		int pos = basePattern.indexOf('.');
103
		if (pos>=0) {
104
			basePattern = basePattern.substring(0, pos+1);
105
		}
106
		if (decimalDigits>0) {
107
			return basePattern + String.format(("%1$0"+decimalDigits+"d"),0);
108
		}
109
		else {
110
			return basePattern;
111
		}
112
	}
113
	
114
	
115
	private CharComboBox getCbDecimalSep() {
116
		if (cbDecimalSep==null) {
117
			cbDecimalSep = new CharComboBox(new String[]{".", ","}, false);
118
			cbDecimalSep.addActionListener(new ActionListener() {
119
				public void actionPerformed(ActionEvent e) {
120
					if (e.getSource() instanceof CharComboBox) {
121
						DecimalFormatPanel.this.updateFormat(e.getSource());
122
					}
123
				}
124
			});
125
		}
126
		return cbDecimalSep;
127
	}
128
	
129
	private CharComboBox getCbThousandsSep() {
130
		if (cbThousandsSep==null) {
131
			cbThousandsSep = new CharComboBox(new String[]{",", ".", " "}, true);
132
			cbThousandsSep.addActionListener(new ActionListener() {
133
				public void actionPerformed(ActionEvent e) {
134
					if (e.getSource() instanceof CharComboBox) {
135
						DecimalFormatPanel.this.updateFormat(e.getSource());
136
					}
137
				}
138
			});
139
		}
140
		return cbThousandsSep;
141
	}
142
	
143
	protected void updateFormat(Object source) {
144
		// get selected values
145
		String thousandsSeparator = getCbThousandsSep().getSelectedItem();
146
		String decimalSeparator = getCbDecimalSep().getSelectedItem();
147
		int decimalDigits = getTfDecimalDigits().getInteger();
148
		boolean b_decimalSep, b_thousandsSep;
149
		DecimalFormatSymbols sym = format.getDecimalFormatSymbols();
150
		if (decimalSeparator!=null && decimalSeparator.length()>0) {
151
			sym.setDecimalSeparator(decimalSeparator.charAt(0));
152
			b_decimalSep = true;
153
		}
154
		else {
155
			b_decimalSep = false;
156
		}
157
		if (thousandsSeparator!=null && thousandsSeparator.length()>0) {
158
			sym.setGroupingSeparator(thousandsSeparator.charAt(0));
159
			b_thousandsSep = true;
160
		}
161
		else {
162
			b_thousandsSep = false;
163
		}
164
		
165
		// choose the right pattern
166
		String pattern = null;
167
		if (b_decimalSep && decimalDigits>0) {
168
			if (b_thousandsSep) {
169
				pattern = getPattern(DECIMAL_GROUPED_BASE_PATTERN, decimalDigits);
170
			}
171
			else {
172
				pattern = getPattern(DECIMAL_BASE_PATTERN, decimalDigits);
173
			}
174
		}
175
		else {
176
			if (b_thousandsSep) {
177
				pattern = INTEGER_GROUPED_BASE_PATTERN;
178
			}
179
			else {
180
				pattern = INTEGER_BASE_PATTERN;
181
			}
182
		}
183
		
184
		// update the format
185
		this.format = new DecimalFormat(pattern, sym);
186
		getLbTestResult().setText(this.format.format(testNumber));
187
		
188
		// set coherent options in UI
189
		if (source==getCbDecimalSep()) {
190
			if (!b_decimalSep) {
191
				// if no decimal separator is shown at all, we can't
192
				// have any decimal digit
193
				getTfDecimalDigits().setInteger(0);
194
			}	
195
		}
196
		else {
197
			if (decimalDigits>0 && !b_decimalSep) {
198
				selectItem(getCbDecimalSep(), String.valueOf(defaultLocaleSymbols.getDecimalSeparator()));
199
			}
200
		}
201
	}             
202
	
203
	private JIncrementalNumberField getTfDecimalDigits() {
204
		if (tfDecimalDigits==null) {
205
			Cleaner cleaner = ValidatingTextField.NUMBER_CLEANER;
206
			Validator validator = ValidatingTextField.INTEGER_VALIDATOR;
207
			tfDecimalDigits = new JIncrementalNumberField("Decimal digits", 2, validator, cleaner, 0.0d, 100.0d, 1.0);
208
			tfDecimalDigits.addActionListener(new ActionListener() {
209

  
210
				public void actionPerformed(ActionEvent e) {
211
					DecimalFormatPanel.this.updateFormat(e.getSource());
212
				}
213
				
214
			});
215
		}
216
		return tfDecimalDigits;
217
	}
218
	
219
	private JLabel getLbTestResult() {
220
		if (lbResult==null) {
221
			String text;
222
			lbResult = new JLabel();
223
		}
224
		return lbResult;
225
	}
226
	
227
	public DecimalFormat getFormat() {
228
		return format;
229
	}
230
	
231
	public void setFormat(DecimalFormat format) {
232
		this.format = format;
233
		getTfDecimalDigits().setInteger(format.getMinimumFractionDigits());
234
		
235
		String decSep = String.valueOf(format.getDecimalFormatSymbols().getDecimalSeparator());
236
		selectItem(getCbDecimalSep(), decSep);
237
		
238
		String thousandsSep = String.valueOf(format.getDecimalFormatSymbols().getGroupingSeparator());
239
		selectItem(getCbThousandsSep(), thousandsSep);
240
	}
241
	
242
	/**
243
	 * Adds the provided item to the combo if it is not already present,
244
	 * then selects it.
245
	 * 
246
	 * @param cb
247
	 * @param item
248
	 * @return
249
	 */
250
	private void selectItem(JComboBox cb, String item) {
251
		for (int i=0; i<cb.getItemCount(); i++) {
252
			if (cb.getItemAt(i).equals(item)) {
253
				cb.setSelectedItem(item);
254
				return;
255
			}
256
		}
257
		cb.addItem(item);
258
		cb.setSelectedItem(item);
259
	}
260
}

Also available in: Unified diff