Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.ui / src / main / java / org / gvsig / gui / beans / swing / JIncrementalNumberField.java @ 40561

History | View | Annotate | Download (10.8 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.gui.beans.swing;
25

    
26
import java.awt.BasicStroke;
27
import java.awt.BorderLayout;
28
import java.awt.Color;
29
import java.awt.Component;
30
import java.awt.Dimension;
31
import java.awt.Graphics;
32
import java.awt.Graphics2D;
33
import java.awt.event.ActionEvent;
34
import java.awt.event.ActionListener;
35
import java.awt.event.FocusEvent;
36
import java.awt.event.FocusListener;
37
import java.awt.event.MouseEvent;
38
import java.awt.event.MouseListener;
39
import java.util.ArrayList;
40
import java.util.Arrays;
41
import java.util.EventListener;
42
import java.util.Iterator;
43
import java.util.Timer;
44
import java.util.TimerTask;
45

    
46
import javax.swing.BorderFactory;
47
import javax.swing.Icon;
48
import javax.swing.JButton;
49
import javax.swing.JPanel;
50
import javax.swing.SwingConstants;
51

    
52
import org.gvsig.gui.beans.Messages;
53
import org.gvsig.gui.beans.swing.ValidatingTextField.Cleaner;
54
import org.gvsig.gui.beans.swing.ValidatingTextField.Validator;
55

    
56
/**
57
 * This class represents a JTextField-like component that allows to input numbers
58
 * and featuring a built-in increment or decrease of the number using the mouse.
59
 * @author jaume dominguez faus - jaume.dominguez@iver.es
60
 */
61
public class JIncrementalNumberField extends JPanel {
62

    
63
        private static final long serialVersionUID = 5225633490545230468L;
64
        private boolean acceptsDoubles;
65
        private ValidatingTextField vtf;
66
        private double step;
67
        private double maxValue;
68
        private double minValue;
69

    
70
        private ActionListener propage = new ActionListener() {
71
                public void actionPerformed(ActionEvent e) {
72
                        if (!isEnabled()) return;
73
                        if (acceptsDoubles) {
74
                                double v = getDouble();
75
                                if (v>maxValue)
76
                                        v = maxValue;
77
                                if (v<minValue)
78
                                        v = minValue;
79
                                setDouble(v);
80
                        } else {
81
                                int v = getInteger();
82
                                if (v>maxValue)
83
                                        v = (int) maxValue;
84
                                if (v<minValue)
85
                                        v = (int) minValue;
86
                                setInteger(v);
87
                        }
88
                        fireActionPerformed(e);
89
                }
90
        };
91

    
92
        private FocusListener propageFocus = new FocusListener() {
93
                public void focusGained(FocusEvent e) {
94
                        if (!isEnabled()) return;
95
                        Iterator<FocusListener> iter = Arrays.asList(JIncrementalNumberField.this.getFocusListeners()).iterator();
96
                        e.setSource(JIncrementalNumberField.this);
97
                        while (iter.hasNext()){
98
                                iter.next().focusGained(e);
99
                        }
100
                }
101

    
102
                public void focusLost(FocusEvent e) {
103
                        if (!isEnabled()) return;
104
                        if (acceptsDoubles) {
105
                                double v = getDouble();
106
                                if (v>maxValue)
107
                                        v = maxValue;
108
                                if (v<minValue)
109
                                        v = minValue;
110
                                setDouble(v);
111
                        } else {
112
                                int v = getInteger();
113
                                if (v>maxValue)
114
                                        v = (int) maxValue;
115
                                if (v<minValue)
116
                                        v = (int) minValue;
117
                                setInteger(v);
118
                        }
119
                        Iterator<FocusListener> iter = Arrays.asList(JIncrementalNumberField.this.getFocusListeners()).iterator();
120
                        e.setSource(JIncrementalNumberField.this);
121
                        while (iter.hasNext()){
122
                                iter.next().focusLost(e);
123
                        }
124
                }
125
        };
126

    
127

    
128
        private ActionListener accum = new ActionListener() {
129
                public void actionPerformed(ActionEvent e) {
130
                        if (!isEnabled()) return;
131
                        String command = e.getActionCommand();
132
                        if ("UP".equals(command)) {
133
                                if (acceptsDoubles) {
134
                                        double v = getDouble() + step;
135
                                        if (v>maxValue)
136
                                                v = maxValue;
137
                                        setDouble(v);
138
                                } else {
139
                                        int v = getInteger() + (int) Math.round(step);
140
                                        if (v>maxValue)
141
                                                v = (int) maxValue;
142
                                        setInteger(v);
143
                                }
144
                        } else if ("DOWN".equals(command)) {
145
                                if (acceptsDoubles) {
146
                                        double v = getDouble();// - step;
147
                                        v = v - step;
148
                                        if (v<minValue)
149
                                                v = minValue;
150
                                        setDouble(v);
151

    
152
                                } else {
153
                                        int v = getInteger() - (int) Math.round(step);
154
                                        if (v<minValue)
155
                                                v = (int) minValue;
156
                                        setInteger(v);
157
                                }
158
                        }
159
                        fireActionPerformed();
160
                }
161
        };
162

    
163
        private JButton down;
164
        private JButton up;
165
        private ArrayList<EventListener> listeners = new ArrayList<EventListener>();
166

    
167
        private class MousePressedTask extends TimerTask {
168
                private MouseEvent e;
169
                private ButtonMouseListener ml;
170

    
171
                private MousePressedTask(ButtonMouseListener ml, MouseEvent e){
172
                        super();
173
                        this.ml = ml;
174
                        this.e = e;
175
                }
176

    
177
                public void run() {
178
                        JButton b = (JButton) e.getComponent();
179

    
180
                        long time = System.currentTimeMillis();
181
                        long delay = 200;
182

    
183
                        while (ml.pressed) {
184
                                if (ml.in) {
185
                                        accum.actionPerformed(new ActionEvent(b, 12431, b.getActionCommand()));
186

    
187
                                        long currTime = System.currentTimeMillis();
188
                                        if (delay > 5 && ((currTime - time) > 1000)) {
189
                                                delay /= 2;
190
                                                time = currTime;
191
                                        }
192
                                } else time = System.currentTimeMillis();
193
                                try {
194
                                        Thread.sleep(delay);
195
                                } catch (InterruptedException e1) {
196
                                        e.consume();
197
                                }
198

    
199
                        }
200
                        e.consume();
201
                }
202
        }
203

    
204
        private class ButtonMouseListener implements MouseListener{
205
                boolean in = false;
206
                boolean pressed = false;
207

    
208
                public void mouseClicked(MouseEvent e) { /* nothing (managed by the ActionListener) */ }
209

    
210
                public void mouseEntered(MouseEvent e) {
211
                        in = true;
212
                }
213

    
214
                public void mouseExited(MouseEvent e) {
215
                        in = false;
216
                }
217

    
218
                public void mousePressed(MouseEvent e) {
219
                        MousePressedTask task;
220
                        synchronized (this) {
221
                                pressed = true;
222
                                Timer timer = new Timer();
223
                                task = new MousePressedTask(this, e);
224
                                timer.schedule(task, 500);
225

    
226
                        }
227
                        if (!pressed) {
228
                                task.cancel();
229
                        }
230

    
231
                }
232

    
233
                public void mouseReleased(MouseEvent e) {
234
                        pressed = false;
235
                }
236

    
237
        };
238

    
239

    
240
        public JIncrementalNumberField() {
241
                this("");
242
        }
243

    
244
        public JIncrementalNumberField(String text) {
245
                this(text, 7);
246
        }
247

    
248
        public JIncrementalNumberField(String text, int columns) {
249
                this(text, columns, ValidatingTextField.DOUBLE_VALIDATOR, ValidatingTextField.NUMBER_CLEANER_2_DECIMALS, -Double.MAX_VALUE, Double.MAX_VALUE, 1);
250
        }
251

    
252
        public JIncrementalNumberField(String text, int columns, double minValue, double maxValue, double step) {
253
                this(text, columns, ValidatingTextField.DOUBLE_VALIDATOR, ValidatingTextField.NUMBER_CLEANER_2_DECIMALS, minValue, maxValue, step);
254
        }
255

    
256
        public JIncrementalNumberField(String text, int columns, Validator validator, Cleaner cleaner, double minValue, double maxValue, double step) {
257
                super();
258
                if (text == null) text = "";
259

    
260
                this.minValue = minValue;
261
                this.maxValue = maxValue;
262
                this.step = step;
263
                acceptsDoubles = validator.getClass().equals(ValidatingTextField.DOUBLE_VALIDATOR.getClass());
264

    
265
                JPanel lateralButtons = new JPanel();
266
                Icon upIcon = new Icon() {
267

    
268
                        public int getIconHeight() {
269
                                return 5;
270
                        }
271

    
272
                        public int getIconWidth() {
273
                                return 9;
274
                        }
275

    
276
                        public void paintIcon(Component c, Graphics g, int x, int y) {
277
                                g.setColor( isEnabled() ? Color.DARK_GRAY : Color.RED);
278
                                ((Graphics2D) g).setStroke(new BasicStroke(2));
279
                                g.drawLine(isEnabled() ? 3 : 1,
280
                                                   isEnabled() ? 6 : 4,
281
                                                   isEnabled() ? 5 : 3,
282
                                                   isEnabled() ? 3 : 1);
283

    
284
                                g.drawLine(isEnabled() ? 5 : 3,
285
                                                   isEnabled() ? 3 : 1,
286
                                                   isEnabled() ? 8 : 6,
287
                                                   isEnabled() ? 6 : 4);
288

    
289
                        }
290
                };
291
                Icon downIcon = new Icon() {
292
                        public int getIconHeight() {
293
                                return 5;
294
                        }
295

    
296
                        public int getIconWidth() {
297
                                return 9;
298
                        }
299

    
300
                        public void paintIcon(Component c, Graphics g, int x, int y) {
301
                                g.setColor(isEnabled() ? Color.DARK_GRAY : Color.RED);
302
                                ((Graphics2D) g).setStroke(new BasicStroke(2));
303

    
304

    
305
                                g.drawLine(isEnabled() ? 3 : 1,
306
                                                   isEnabled() ? 3 : 1,
307
                                                   isEnabled() ? 5 : 3,
308
                                                   isEnabled() ? 6 : 4);
309

    
310
                                g.drawLine(isEnabled() ? 5 : 3,
311
                                                   isEnabled() ? 6 : 4,
312
                                                   isEnabled() ? 8 : 6,
313
                                                   isEnabled() ? 3 : 1);
314

    
315
                        }
316
                };
317
                up = new JButton(upIcon);
318
                up.setActionCommand("UP");
319
                up.addActionListener(accum);
320
                up.addMouseListener(new ButtonMouseListener());
321
                up.setBounds(0, 0, 11, 11);
322
                up.setFocusable(false);
323

    
324
                down = new JButton(downIcon);
325
                down.setActionCommand("DOWN");
326
                down.addActionListener(accum);
327
                down.addMouseListener(new ButtonMouseListener());
328
                down.setBounds(0, 11, 11, 11);
329
                down.setFocusable(false);
330

    
331

    
332

    
333
                lateralButtons.setLayout(null);
334
                lateralButtons.setSize(13, 20);
335
                lateralButtons.add(up);
336
                lateralButtons.add(down);
337
                lateralButtons.setSize(new Dimension(11, 22));
338
                lateralButtons.setPreferredSize(new Dimension(11, 22));
339
                lateralButtons.setBorder(BorderFactory.createLineBorder(Color.GREEN));
340
                vtf = new ValidatingTextField(
341
                                text,
342
                                columns,
343
                                SwingConstants.RIGHT,
344
                                validator,
345
                                cleaner) ;
346
                setLayout(new BorderLayout(0, 0));
347
                vtf.addActionListener(propage);
348
                vtf.addFocusListener(propageFocus);
349
                add(vtf, BorderLayout.CENTER);
350
                add(lateralButtons, BorderLayout.EAST);
351
        }
352

    
353
        public int getInteger() {
354
                return vtf.getInteger();
355
        }
356

    
357
        public double getDouble() {
358
                if (!acceptsDoubles)
359
                        throw new Error(Messages.getText(
360
                                        "cannot_get_double_value_from_an_integer_number_field_use_getInteger()_instead"));
361
                return vtf.getDouble();
362
        }
363

    
364
        public void setDouble(double v) {
365
                if (!acceptsDoubles)
366
                        throw new Error(Messages.getText(
367
                                        "cannot_set_a_double_value_from_an_integer_number_field_use_setInteger(int)_instead"));
368
                vtf.setText(String.valueOf(v));
369
        }
370

    
371
        public void setInteger(int v) {
372
                vtf.setText(String.valueOf(v));
373
        }
374

    
375
        public void addActionListener(ActionListener l) {
376
//                vtf.addActionListener(l);
377
                listeners.add(l);
378
        }
379

    
380
        public void removeActionListener(ActionListener l) {
381
//                vtf.removeActionListener(l);
382
                listeners.remove(l);
383
        }
384

    
385
        private void fireActionPerformed() {
386
                ActionEvent evt = new ActionEvent(this, 0, null);
387
                for (int i = 0; i < listeners.size(); i++) {
388
                        ((ActionListener) listeners.get(i)).actionPerformed(evt);
389
                }
390
        }
391

    
392
        private void fireActionPerformed(ActionEvent e) {
393
                e.setSource(this);
394
                for (int i = 0; i < listeners.size(); i++) {
395
                        ((ActionListener) listeners.get(i)).actionPerformed(e);
396
                }
397
        }
398

    
399
        public double getMaxValue() {
400
                return maxValue;
401
        }
402

    
403
        public void setMaxValue(double maxValue) {
404
                this.maxValue = maxValue;
405
        }
406

    
407
        public double getMinValue() {
408
                return minValue;
409
        }
410

    
411
        public void setMinValue(double minValue) {
412
                this.minValue = minValue;
413
        }
414

    
415
        public double getStep() {
416
                return step;
417
        }
418

    
419
        public void setStep(double step) {
420
                this.step = step;
421
        }
422

    
423
        public void setEnabled(boolean enabled) {
424
                super.setEnabled(enabled);
425
                up.setEnabled(enabled);
426
                down.setEnabled(enabled);
427
                vtf.setEnabled(enabled);
428
        }
429
}