View Javadoc

1   /*
2    * AmountSpinnerPanel.java Created @ Jun 22, 2004
3    * 
4    * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628 BX
5    * Delft, the Netherlands. All rights reserved.
6    * 
7    * See for project information <a href="http://www.simulation.tudelft.nl/">
8    * www.simulation.tudelft.nl </a>.
9    * 
10   * The source code and binary code of this software is proprietary information
11   * of Delft University of Technology.
12   * 
13   */
14  package org.gscg.common.gui.components;
15  
16  import info.clearthought.layout.TableLayout;
17  
18  import java.awt.Color;
19  import java.awt.Component;
20  import java.awt.event.MouseEvent;
21  import java.awt.event.MouseListener;
22  
23  import javax.swing.BoxLayout;
24  import javax.swing.JButton;
25  import javax.swing.JOptionPane;
26  import javax.swing.JPanel;
27  import javax.swing.SpinnerModel;
28  import javax.swing.SwingConstants;
29  import javax.swing.event.ChangeListener;
30  
31  import nl.tudelft.simulation.logger.Logger;
32  
33  import org.gscg.common.gui.components.interactivespinner.JFormattedTextField;
34  import org.gscg.common.gui.components.interactivespinner.JInteractiveSpinner;
35  import org.gscg.common.gui.components.interactivespinner.SpinnerNumberModel;
36  
37  
38  /***
39   * The AmountSpinnerModel is a spinner model to indicate the amount for a
40   * product. <br>
41   * 
42   * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628 BX
43   * Delft, the Netherlands. All rights reserved.
44   * 
45   * See for project information <a href="http://www.simulation.tudelft.nl/">
46   * www.simulation.tudelft.nl </a>.
47   * 
48   * The source code and binary code of this software is proprietary information
49   * of Delft University of Technology.
50   * 
51   * @author <a
52   *         href="http://www.tbm.tudelft.nl/webstaf/stijnh/index.htm">Stijn-Pieter
53   *         van Houten </a>* *
54   * @version $Revision: 1.1 $ $Date: 2005/06/16 12:33:53 $
55   * @since 1.0.0 <br>
56   */
57  public class AmountSpinnerPanel extends JPanel implements MouseListener
58  {
59  	/*** the serial version uid */
60  	private static final long serialVersionUID = 11L;
61  
62  	/*** the name of the spinner */
63  	public static final String AMOUNT_SPINNER_NAME = "AMOUNT_SPINNER";
64  
65  	/*** the day spinner */
66  	private JInteractiveSpinner spinner = null;
67  
68  	/*** the minimum */
69  	private double minimum = 1.0;
70  
71  	/*** the maximum */
72  	private double maximum = 1000;
73  
74  	/*** the step size */
75  	private int stepSize = 1;
76  
77  	/*** the initial value */
78  	private int initialvalue = 0;
79  
80  	/*** indicates whether the spinner is being changed */
81  	private boolean pressed = false;
82  
83  	/*** the thread for increasing the stepsize */
84  	private IncreaseStepSizeThread increaseThread = null;
85  
86  	/*** the formatted text field */
87  	private JFormattedTextField ftf = null;
88  
89  	/***
90  	 * constructs a new AmountSpinnerPanel, initializes the spinner with a
91  	 * minimum of 1, a maximum of 1000 and a stepsize of 1
92  	 * 
93  	 * @param editable indicates whether the spinner is editable
94  	 * @param initialvalue the initial value of the spinner
95  	 */
96  	public AmountSpinnerPanel(final boolean editable, final int initialvalue)
97  	{
98  		this(editable, 1.0, 1000.0, 1, initialvalue);
99  	}
100 
101 	/***
102 	 * 
103 	 * constructs a new AmountSpinnerPanel
104 	 * 
105 	 * @param editable indicates whether the spinner is editable
106 	 * @param minimum the minimum value
107 	 * @param maximum the maximum value
108 	 * @param stepsize the step size
109 	 * @param initialvalue the initial value of the spinner
110 	 */
111 	public AmountSpinnerPanel(final boolean editable, final double minimum,
112 			final double maximum, final int stepsize, final int initialvalue)
113 	{
114 		this(editable, minimum, maximum, stepsize, initialvalue, null);
115 	}
116 
117 
118 	/***
119 	 * constructs a new AmountSpinnerPanel
120 	 * 
121 	 * @param editable indicates whether the spinner is editable
122 	 * @param minimum the minimum value
123 	 * @param maximum the maximum value
124 	 * @param stepsize the step size
125 	 * @param initialvalue the initial value of the spinner
126 	 * @param changeListener the changelistener, may be null
127 	 */
128 	public AmountSpinnerPanel(final boolean editable, final double minimum,
129 			final double maximum, final int stepsize, final int initialvalue,
130 			final ChangeListener[] changeListener)
131 	{
132 		super();
133 
134 		try
135 		{
136 			this.minimum = minimum;
137 			this.maximum = maximum;
138 			this.stepSize = stepsize;
139 			this.initialvalue = initialvalue;
140 
141 			double[][] layout = {{250}, {20}};
142 			this.setLayout(new TableLayout(layout));
143 			this.setOpaque(false);
144 
145 			JPanel amountParametersPanel = new JPanel();
146 			amountParametersPanel.setLayout(new BoxLayout(
147 					amountParametersPanel, BoxLayout.X_AXIS));
148 			amountParametersPanel.setOpaque(false);
149 
150 			this.add(amountParametersPanel, "0,0,L,C");
151 			String[] labels = {""};
152 
153 			// add the abel-spinner pair
154 			SpinnerModel amountModel = new SpinnerNumberModel(
155 					this.initialvalue, // initial
156 					// value
157 					this.minimum, // min
158 					this.maximum, // max
159 					this.stepSize); // step
160 
161 			this.spinner = SpinnerUtilities.addLabeledInteractiveSpinner(
162 					amountParametersPanel, labels[0], amountModel);
163 			this.spinner.setEnabled(editable);
164 			this.spinner.setName(AmountSpinnerPanel.AMOUNT_SPINNER_NAME);
165 
166 			// we add the changelistener, if not null
167 			if (changeListener != null)
168 			{
169 				for (int i = 0; i < changeListener.length; i++)
170 				{
171 					this.spinner.addChangeListener(changeListener[i]);
172 				}
173 			}
174 
175 			// we implement a mouse listener to play with increased stepsize as
176 			// the spinner has been pressed
177 			Object[] keys = this.spinner.getComponents();
178 			for (int i = 0; i < keys.length; i++)
179 			{
180 				Object obj = this.spinner.getComponents()[i];
181 				if (JButton.class.isAssignableFrom(obj.getClass()))
182 				{
183 					((JButton) obj).addMouseListener(this);
184 				}
185 			}
186 
187 			// tweak the spinner's formatted text field.
188 			this.ftf = null;
189 
190 			this.ftf = SpinnerUtilities.getTextField(this.spinner);
191 			if (this.ftf != null)
192 			{
193 				this.ftf.setColumns(5); // specify more width than we need
194 				this.ftf.setHorizontalAlignment(SwingConstants.RIGHT);
195 				this.ftf.setEditable(true); // set the textfield editable
196 				this.ftf.setSelectionColor(Color.BLUE);
197 				this.ftf.setSelectedTextColor(Color.WHITE);
198 			}
199 		} catch (Exception exception)
200 		{
201 			exception.printStackTrace();
202 		}
203 	}
204 
205 	/***
206 	 * @return Returns the spinner.
207 	 */
208 	public JInteractiveSpinner getSpinner()
209 	{
210 		return this.spinner;
211 	}
212 
213 	/***
214 	 * @return returns the amount of the spinner
215 	 */
216 	public double getAmount()
217 	{
218 		double amount = Double.NaN;
219 		try
220 		{
221 			amount = new Double(this.ftf.getText()).doubleValue();
222 
223 			if (!this.ftf.isEditValid())
224 			{
225 				JOptionPane
226 						.showConfirmDialog(
227 								(Component) null,
228 								"The value you entered for the amount is either too large or too small, please adjust the value.",
229 								"Warning", JOptionPane.DEFAULT_OPTION,
230 								JOptionPane.WARNING_MESSAGE);
231 				return -Double.MAX_VALUE;
232 			}
233 		} catch (Exception exception)
234 		{
235 			return -Double.MAX_VALUE;
236 		}
237 		return amount;
238 	}
239 
240 	/***
241 	 * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
242 	 */
243 	public void mouseClicked(final MouseEvent e)
244 	{
245 		// nothing to do
246 	}
247 
248 	/***
249 	 * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
250 	 */
251 	public void mouseEntered(final MouseEvent e)
252 	{
253 		// nothing to do
254 	}
255 
256 	/***
257 	 * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
258 	 */
259 	public void mouseExited(final MouseEvent e)
260 	{
261 		// nothing to do
262 	}
263 
264 	/***
265 	 * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
266 	 */
267 	public void mousePressed(final MouseEvent e)
268 	{
269 		this.pressed = true;
270 		this.increaseThread = new IncreaseStepSizeThread(this);
271 		this.increaseThread.start();
272 	}
273 
274 	/***
275 	 * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
276 	 */
277 	public void mouseReleased(final MouseEvent e)
278 	{
279 		this.pressed = false;
280 		try
281 		{
282 			this.increaseThread = null;
283 			// reset the spinner model
284 			SpinnerModel model = new SpinnerNumberModel(((Double) this.spinner
285 					.getValue()).doubleValue(), // initial
286 					// value
287 					this.minimum, // min
288 					this.maximum, // max
289 					this.stepSize); // step
290 			this.spinner.setModel(model);
291 		} catch (Exception exception)
292 		{
293 			Logger.severe(this, "mouseReleased", exception);
294 		}
295 	}
296 
297 	/***
298 	 * A thread used to increase the stepsize while the mouse button (either
299 	 * increase or decrease) is being pressed.
300 	 * <p>
301 	 * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628
302 	 * BX Delft, the Netherlands. All rights reserved.
303 	 * 
304 	 * See for project information <a href="http://www.simulation.tudelft.nl/">
305 	 * www.simulation.tudelft.nl </a>.
306 	 * 
307 	 * The source code and binary code of this software is proprietary
308 	 * information of Delft University of Technology.
309 	 * 
310 	 * @author <a
311 	 *         href="http://www.tbm.tudelft.nl/webstaf/stijnh/index.htm">Stijn-Pieter
312 	 *         van Houten </a>
313 	 * @version $Revision: 1.1 $ $Date: 2005/06/16 12:33:53 $
314 	 * @since 1.0.6
315 	 */
316 	private class IncreaseStepSizeThread extends Thread
317 	{
318 		/*** the owner */
319 		private AmountSpinnerPanel owner = null;
320 
321 		/***
322 		 * constructs a new increaseStepSizeThread
323 		 * 
324 		 * @param owner the owner
325 		 */
326 		public IncreaseStepSizeThread(final AmountSpinnerPanel owner)
327 		{
328 			this.owner = owner;
329 		}
330 
331 		/***
332 		 * @see java.lang.Runnable#run()
333 		 */
334 		public void run()
335 		{
336 			super.run();
337 
338 			// if only cicked once, we must sleep a little
339 			// while and than check whether we should run
340 			try
341 			{
342 				Thread.sleep(500);
343 				int count = 0;
344 				while (this.owner.pressed)
345 				{
346 					count++;
347 					double stepSize = this.owner.stepSize * count;
348 					if (stepSize > (this.owner.maximum - ((Double) this.owner.spinner
349 							.getValue()).doubleValue()))
350 					{
351 						stepSize = this.owner.maximum
352 								- ((Double) this.owner.spinner.getValue())
353 										.doubleValue();
354 					}
355 					if (stepSize > (((Double) this.owner.spinner.getValue())
356 							.doubleValue() - this.owner.minimum))
357 					{
358 						stepSize = ((Double) this.owner.spinner.getValue())
359 								.doubleValue()
360 								- this.owner.minimum;
361 					}
362 					SpinnerModel model = new SpinnerNumberModel(
363 							((Double) this.owner.spinner.getValue())
364 									.doubleValue(),
365 							// current value
366 							this.owner.minimum, // min
367 							this.owner.maximum, // max
368 							stepSize); // step
369 					this.owner.spinner.setModel(model);
370 
371 					// we sleep before increasing the time step
372 					Thread.sleep(100);
373 				}
374 			} catch (Exception exception)
375 			{
376 				Logger.severe(this, "run", exception);
377 			}
378 		}
379 	}
380 }