View Javadoc

1   /*
2    * Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton,
3    * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
4    *
5    * THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
6    * WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
7    * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
8    * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
9    * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
10   * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
11   * THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
12   * IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
13   * CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
14   * NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
15   * DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
16   * OR MODIFICATIONS.
17   * THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
18   * USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
19   * PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
20   * AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
21   */
22  
23  package de.desy.acop.displayers.tools;
24  
25  import java.awt.GridBagConstraints;
26  import java.awt.GridBagLayout;
27  import java.awt.GridLayout;
28  import java.awt.Insets;
29  import java.awt.event.ActionEvent;
30  import java.awt.event.ActionListener;
31  import java.beans.PropertyChangeEvent;
32  import java.beans.PropertyChangeListener;
33  
34  import javax.swing.ButtonGroup;
35  import javax.swing.JButton;
36  import javax.swing.JPanel;
37  import javax.swing.JRadioButton;
38  import javax.swing.JSpinner;
39  import javax.swing.SpinnerNumberModel;
40  import javax.swing.event.ChangeEvent;
41  import javax.swing.event.ChangeListener;
42  
43  import com.cosylab.gui.components.util.RunnerHelper;
44  
45  /**
46   * <code>RecentTimeSpanSelector</code> enables selection of a time span
47   * which starts at specified time in the past and ends now. User can specifiy
48   * the starting date by rolling back 'now' for a selected number of
49   * minutes, hours or days.
50   * <p>
51   * This class is an extension of the </code>javax.swing.JPanel</code> therefore
52   * allowing all properties provided by the swing hierarchy. In addition to those 
53   * properties, this class also provides a readable property <code>timeSpan</code>
54   * which describes the span selected in the GUI.
55   * </p>
56   * 
57   * @author Tilen Kusterle, Cosylab
58   *
59   */
60  public class RecentTimespanSelector extends JPanel {
61  	
62  	private static final long serialVersionUID = 1L;
63  	
64  	public static final String TIME_SPAN = "timeSpan";
65  	
66  	private static final int SECS = 60;
67  	private static final int MINS = 60;
68  	private static final int DAY = 24;
69  	
70  	private int min = 1;
71  	private int hour = 1;
72  	private int day = 1;
73  	
74  	private SpinnerNumberModel minModel;
75  	private SpinnerNumberModel hourModel;
76  	private SpinnerNumberModel dayModel;
77  	
78  	private JSpinner minSpin;
79  	private JSpinner hourSpin;
80  	private JSpinner daySpin;
81  	
82  	private ButtonGroup group;
83  	
84  	private JRadioButton minRButton;
85  	private JRadioButton hourRButton;
86  	private JRadioButton dayRButton;
87  	
88  	private JRadioButton wasSelected;
89  	
90  	private JButton applyButton;
91  	private JButton cancelButton;
92  	
93  	private double timeSpan;
94  	
95  	/**
96  	 * Constructs a new RecentTimespanSelector
97  	 *
98  	 */
99  	public RecentTimespanSelector() {
100 		initialize();
101 	}
102 	
103 	private void initialize() {
104 		minRButton = new JRadioButton("Minutes");
105 		minRButton.setSelected(true);
106 		wasSelected = minRButton;
107 		minRButton.addActionListener(new ActionListener() {
108 			public void actionPerformed(ActionEvent e) {
109 				if (minRButton.isSelected()) {
110 					performSelectedAction(minRButton);
111 				}
112 			}});
113 		hourRButton = new JRadioButton("Hours");
114 		hourRButton.setSelected(false);
115 		hourRButton.addActionListener(new ActionListener() {
116 			public void actionPerformed(ActionEvent e) {
117 				if (hourRButton.isSelected()) {
118 					performSelectedAction(hourRButton);
119 				}
120 			}});
121 		dayRButton = new JRadioButton("Days");
122 		dayRButton.setSelected(false);
123 		dayRButton.addActionListener(new ActionListener() {
124 			public void actionPerformed(ActionEvent e) {
125 				if (dayRButton.isSelected()) {
126 					performSelectedAction(dayRButton);
127 				}
128 			}});
129 		
130 		group = new ButtonGroup();
131 		group.add(minRButton);
132 		group.add(hourRButton);
133 		group.add(dayRButton);
134 		
135 		minModel = new SpinnerNumberModel(1,1,59,1);
136 		hourModel = new SpinnerNumberModel(1,1,23,1);
137 		dayModel = new SpinnerNumberModel(1,1,99,1);
138 		
139 		minSpin = new JSpinner(minModel);
140 		minSpin.setToolTipText("Set Recent Past in Minutes");
141 		hourSpin = new JSpinner(hourModel);
142 		hourSpin.setToolTipText("Set Recent Past in Hours");
143 		hourSpin.setEnabled(false);
144 		hourSpin.setValue(0);
145 		daySpin = new JSpinner(dayModel);
146 		daySpin.setToolTipText("Set Recent Past in Days");
147 		daySpin.setEnabled(false);
148 		daySpin.setValue(0);
149 		
150 		minSpin.addChangeListener(new ChangeListener() {
151 			public void stateChanged(ChangeEvent evt) {
152 				if(min != minModel.getNumber().intValue()) {
153 					setButtonsEnabled(true);
154 				}
155 				else {
156 					setButtonsEnabled(false);
157 				}
158 	        }
159 		});
160 		
161 		hourSpin.addChangeListener(new ChangeListener() {
162 			public void stateChanged(ChangeEvent evt) {
163 				if(hour != hourModel.getNumber().intValue()) {
164 					setButtonsEnabled(true);
165 				}
166 				else {
167 					setButtonsEnabled(false);
168 				}
169 	        }
170 		});
171 		
172 		daySpin.addChangeListener(new ChangeListener() {
173 			public void stateChanged(ChangeEvent evt) {
174 				if(day != dayModel.getNumber().intValue()) {
175 					setButtonsEnabled(true);
176 				}
177 				else {
178 					setButtonsEnabled(false);
179 				}
180 	        }
181 		});
182 		
183 		setLayout(new GridBagLayout());
184 		JPanel spinPanel = new JPanel(new GridBagLayout());
185 		spinPanel.add(minRButton,new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, 0, new Insets(4,4,4,4), 0, 0));
186 		spinPanel.add(hourRButton,new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.WEST, 0, new Insets(4,4,4,4), 0, 0));
187 		spinPanel.add(dayRButton,new GridBagConstraints(0, 2, 1, 1, 0, 0, GridBagConstraints.WEST, 0, new Insets(4,4,4,4), 0, 0));
188 		spinPanel.add(minSpin,new GridBagConstraints(1, 0, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(4,4,4,4), 0, 0));
189 		spinPanel.add(hourSpin,new GridBagConstraints(1, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(4,4,4,4), 0, 0));
190 		spinPanel.add(daySpin,new GridBagConstraints(1, 2, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(4,4,0,4), 0, 0));
191 		
192 		add(spinPanel, new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,0,0,0),0,0));
193 		
194 		JPanel buttonsPanRecent = new JPanel();
195 		buttonsPanRecent.setLayout(new GridLayout(1,2, 20, 4));
196 		buttonsPanRecent.add(getApplyButton());
197 		buttonsPanRecent.add(getCancelButton());
198 		
199 		add(buttonsPanRecent,new GridBagConstraints(0, 3, 2, 1, 0, 0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(4,4,11,4), 0, 0));
200 		
201 	}
202 	
203 	private JButton getApplyButton() {
204 		if (applyButton == null) {
205 			applyButton = new JButton("Apply");
206 			applyButton.addActionListener(new ActionListener() {
207 				public void actionPerformed(ActionEvent event) {
208 					double oldValue = getTimeSpan();
209 					setTimeSpan(calculateRecentPast());
210 					setButtonsEnabled(false);
211 					if (minRButton.isSelected()) wasSelected = minRButton;
212 					else if (hourRButton.isSelected()) wasSelected = hourRButton;
213 					else wasSelected = dayRButton;
214 					firePropertyChange(TIME_SPAN, oldValue, getTimeSpan());
215 				}	
216 			});
217 			applyButton.setToolTipText("Apply Recent Past Selection");
218 		}	
219 		return applyButton;
220 	}
221 	
222 	private JButton getCancelButton() {
223 		if (cancelButton == null) {
224 			cancelButton = new JButton("Cancel");
225 			cancelButton.addActionListener(new ActionListener() {
226 				public void actionPerformed(ActionEvent event) {
227 					wasSelected.setSelected(true);
228 					performSelectedAction(wasSelected);
229 				}	
230 			});
231 			cancelButton.setToolTipText("Cancel Recent Past Selection");
232 		}	
233 		return cancelButton;
234 	}
235 	
236 	/**
237 	 * Enables the Apply and cancel buttons.
238 	 * 
239 	 * @param enable
240 	 */
241 	public void setButtonsEnabled(boolean enable) {
242 	    getApplyButton().setEnabled(enable);
243 	    getCancelButton().setEnabled(enable);
244 	}
245 	
246 	private double calculateRecentPast() {
247 		
248 		if (minRButton.isSelected()) {
249 			min = minModel.getNumber().intValue();
250 			return min*SECS;
251 		}
252 		else if (hourRButton.isSelected()) {
253 			hour = hourModel.getNumber().intValue();
254 			return hour*MINS*SECS;
255 		}
256 		else {
257 			day = dayModel.getNumber().intValue();
258 			return day*DAY*MINS*SECS;
259 		}
260 	}
261 	
262 	/**
263 	 * Returns the selected time span.
264 	 * @return the timeSpan
265 	 */
266 	public double getTimeSpan() {
267 		return timeSpan;
268 	}
269 	
270 	/**
271 	 * Sets selected time span.
272 	 * @param timeSpan the timeSpan to set
273 	 */
274 	public void setTimeSpan(double timeSpan) {
275 		this.timeSpan = timeSpan;
276 	}
277 	
278 	private void performSelectedAction(JRadioButton button) {
279 		if (button.equals(minRButton)) {
280 			hourSpin.setEnabled(false);
281 			hourSpin.setValue(0);
282 			daySpin.setEnabled(false);
283 			daySpin.setValue(0);
284 			minSpin.setEnabled(true);
285 			minSpin.setValue(min);
286 			
287 		}
288 		else if (button.equals(hourRButton)) {
289 			minSpin.setEnabled(false);
290 			minSpin.setValue(0);
291 			daySpin.setEnabled(false);
292 			daySpin.setValue(0);
293 			hourSpin.setEnabled(true);
294 			hourSpin.setValue(hour);
295 		}
296 		else {
297 			minSpin.setEnabled(false);
298 			minSpin.setValue(0);
299 			hourSpin.setEnabled(false);
300 			hourSpin.setValue(0);
301 			daySpin.setEnabled(true);
302 			daySpin.setValue(day);
303 		}
304 		if (calculateRecentPast() == getTimeSpan()) {
305 			setButtonsEnabled(false);
306 		}
307 		else setButtonsEnabled(true);
308 	}
309 
310 	/* (non-Javadoc)
311 	 * @see javax.swing.JComponent#setEnabled(boolean)
312 	 */
313 	@Override
314 	public void setEnabled(boolean enabled) {
315 		super.setEnabled(enabled);
316 		minRButton.setEnabled(enabled);
317 		hourRButton.setEnabled(enabled);
318 		dayRButton.setEnabled(enabled);
319 		if (enabled) {
320 			if (minRButton.isSelected()) {
321 				minSpin.setEnabled(enabled);
322 			}
323 			else if (hourRButton.isSelected()) {
324 				hourSpin.setEnabled(enabled);
325 			}
326 			else {
327 				daySpin.setEnabled(enabled);
328 			}
329 			if (calculateRecentPast() != getTimeSpan()) setButtonsEnabled(enabled);
330 		}
331 		else {
332 			minSpin.setEnabled(enabled);
333 			hourSpin.setEnabled(enabled);
334 			daySpin.setEnabled(enabled);
335 			setButtonsEnabled(enabled);
336 		}
337 		
338 	}
339 	
340 	public static void main(String[] args) {
341 		RecentTimespanSelector tss = new RecentTimespanSelector();
342 		tss.addPropertyChangeListener(TIME_SPAN, new PropertyChangeListener() {
343 
344 			public void propertyChange(PropertyChangeEvent evt) {
345 				System.out.println(evt.getNewValue());
346 				
347 			}});
348 		RunnerHelper.runComponent(tss, 300, 400);
349 	}
350 
351 }