View Javadoc

1   /*
2    * Copyright (c) 2003-2008 by Cosylab d. d.
3    *
4    * This file is part of CosyBeans.
5    *
6    * CosyBeans is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation, either version 3 of the License, or
9    * (at your option) any later version.
10   *
11   * CosyBeans 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 CosyBeans.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  package com.cosylab.gui;
21  
22  import java.awt.event.ActionEvent;
23  import java.beans.PropertyVetoException;
24  import java.util.Map;
25  
26  import javax.swing.AbstractAction;
27  
28  import com.cosylab.application.state.State;
29  import com.cosylab.events.SetEvent;
30  import com.cosylab.events.SetListener;
31  import com.cosylab.gui.adapters.Converter;
32  import com.cosylab.gui.components.AbstractDisplayerPanel;
33  import com.cosylab.gui.components.LabelledNumberField;
34  import com.cosylab.gui.components.util.PopupManager;
35  import com.cosylab.gui.components.util.RunnerHelper;
36  import com.cosylab.gui.displayers.ConvertibleDisplayer;
37  import com.cosylab.gui.displayers.DataConsumer;
38  import com.cosylab.gui.displayers.DataSource;
39  import com.cosylab.gui.displayers.DataSourceSupport;
40  import com.cosylab.gui.displayers.DataState;
41  import com.cosylab.gui.displayers.DisplayerUtilities;
42  import com.cosylab.gui.displayers.DoubleConsumer;
43  import com.cosylab.gui.displayers.DoubleConsumerMulticaster;
44  import com.cosylab.gui.displayers.DoubleDisplayer;
45  import com.cosylab.gui.displayers.NonblockingNumberConsumer;
46  
47  
48  /**
49   * <code>DoubleNumberDisplayer</code> is simple implementation of
50   * <code>DoubleDisplayer</code> interface based on
51   * <code>LabelledNumberfield</code>.
52   *
53   * @author <a href="mailto:igor.kriznar@cosylab.com">Igor Kriznar</a>
54   * @author <a href="mailto:jernej.kamenik@cosylab.com">Jernej Kamenik</a>
55   * @version $Id: DoubleNumberDisplayer.java,v 1.16 2008-04-22 12:31:02 jbobnar Exp $
56   *
57   * @since Nov 24, 2003.
58   */
59  public class DoubleNumberDisplayer extends LabelledNumberField
60  	implements DoubleDisplayer, DataSource, ConvertibleDisplayer
61  {
62  	private static final long serialVersionUID = 1L;
63  
64  	public static void main(String[] args) {
65  		DoubleNumberDisplayer disp = new DoubleNumberDisplayer();
66  		disp.setPopupEnabled(false);
67  		RunnerHelper.runComponent(disp, 300,300);
68  	}
69  	@SuppressWarnings("unchecked")
70  	private DataSourceSupport support = new DataSourceSupport(new Class[]{
71  			    NonblockingNumberConsumer.class
72  		    });
73  	private DataState dataState = new DataState(DataState.UNDEFINED);
74  	private int suspendCount = 0;
75  	private DataSource dataSource;
76  	private Converter converter;
77  	private InfoDialog infoDialog;
78  	private PopupManager popupManager;
79  
80  	/**
81  	 * Creates WheelswitchDisplayer displayer.
82  	 *
83  	 * @param newValue
84  	 */
85  	public DoubleNumberDisplayer(double newValue)
86  	{
87  		this(newValue, true, true, false);
88  	}
89  
90  	/**
91  	 * Creates WheelswitchDisplayer displayer.
92  	 */
93  	public DoubleNumberDisplayer()
94  	{
95  		this(0.0);
96  	}
97  
98  	/**
99  	 * Creates WheelswitchDisplayer displayer.
100 	 *
101 	 * @param value inital value
102 	 * @param resizable initial resizable flag
103 	 * @param enchanced initial antialiasing flag
104 	 * @param unitsWithTitle shows units in title label
105 	 */
106 	public DoubleNumberDisplayer(double value, boolean resizable,
107 	    boolean enchanced, boolean unitsWithTitle)
108 	{
109 		super(new Double(value), "%+3.2f", "Double Number Field", null, resizable,
110 		    enchanced, true, unitsWithTitle);
111 		initialize();
112 	}
113 
114 	/* (non-Javadoc)
115 	 * @see com.cosylab.gui.displayers.DataConsumer#setAttributes(java.util.Map)
116 	 */
117 	public void setCharacteristics(Map characteristics)
118 	{
119 		if (characteristics == null) {
120 			throw new NullPointerException("characteristics");
121 		}
122 
123 		DisplayerUtilities.setCharacteristics(characteristics, this);
124 	}
125 
126 	/* (non-Javadoc)
127 	 * @see com.cosylab.gui.displayers.DataSource#getConsumers()
128 	 */
129 	public DataConsumer[] getConsumers()
130 	{
131 		return support.getConsumers();
132 	}
133 
134 	/* (non-Javadoc)
135 	 * @see com.cosylab.gui.displayers.DataConsumer#getDataConsumer(java.lang.Class)
136 	 */
137 	public DataConsumer getDataConsumer(Class type)
138 	{
139 		if (type == DoubleConsumer.class) {
140 			return this;
141 		}
142 
143 		return DoubleConsumerMulticaster.createDataConsumer(type, this);
144 	}
145 
146 	/* (non-Javadoc)
147 	 * @see com.cosylab.gui.displayers.CommonDisplayer#getDataState()
148 	 */
149 	public DataState getDataState()
150 	{
151 		return dataState;
152 	}
153 
154 	/* (non-Javadoc)
155 	 * @see com.cosylab.gui.displayers.DataConsumer#getDefaultDataConsumer()
156 	 */
157 	public DataConsumer getDefaultDataConsumer()
158 	{
159 		return this;
160 	}
161 
162 	/* (non-Javadoc)
163 	 * @see com.cosylab.gui.displayers.DoubleDisplayer#setGraphMax(double)
164 	 */
165 	public void setMaximum(double value)
166 	{
167 		super.setMaximumValue(new Double(value));
168 	}
169 
170 	/* (non-Javadoc)
171 	 * @see com.cosylab.gui.displayers.DoubleDisplayer#getGraphMax()
172 	 */
173 	public double getMaximum()
174 	{
175 		return super.getMaximumValue().doubleValue();
176 	}
177 
178 	/* (non-Javadoc)
179 	 * @see com.cosylab.gui.displayers.DoubleDisplayer#setGraphMin(double)
180 	 */
181 	public void setMinimum(double value)
182 	{
183 		super.setMinimumValue(new Double(value));
184 	}
185 
186 	/* (non-Javadoc)
187 	 * @see com.cosylab.gui.displayers.DoubleDisplayer#getGraphMin()
188 	 */
189 	public double getMinimum()
190 	{
191 		return super.getMinimumValue().doubleValue();
192 	}
193 
194 	/**
195 	 * Overriden to implement additional features loading.
196 	 *
197 	 * @param state to be loaded.
198 	 */
199 	public void setState(State state)
200 	{
201 		super.setState(state);
202 
203 		setMaximum(state.getDouble("maximum", getMaximum()));
204 		setMinimum(state.getDouble("minimum", getMinimum()));
205 	}
206 
207 	/**
208 	 * Overriden to implement additional features saving.
209 	 *
210 	 * @return state of the component.
211 	 */
212 	public State getState()
213 	{
214 		State state = super.getState();
215 
216 		state.putDouble("maximum", getMaximum());
217 		state.putDouble("minimum", getMinimum());
218 
219 		return state;
220 	}
221 
222 	/* (non-Javadoc)
223 	 * @see com.cosylab.gui.displayers.CommonDisplayer#getSupportedAttributes()
224 	 */
225 	public String[] getSupportedCharacteristics()
226 	{
227 		return DisplayerUtilities.COMMON_NUMERIC_DISPLAYER_CHARACTERISTICS;
228 	}
229 
230 	/* (non-Javadoc)
231 	 * @see com.cosylab.gui.displayers.DataSource#getSupportedConsumersTypes()
232 	 */
233 	@SuppressWarnings("unchecked")
234 	public Class[] getAcceptableConsumerTypes()
235 	{
236 		return support.getAcceptableConsumerTypes();
237 	}
238 
239 	/* (non-Javadoc)
240 	 * @see com.cosylab.gui.displayers.CommonDisplayer#isSuspended()
241 	 */
242 	public boolean isSuspended()
243 	{
244 		return suspendCount > 0;
245 	}
246 
247 	/* (non-Javadoc)
248 	 * @see com.cosylab.gui.displayers.DoubleDisplayer#setValue(double)
249 	 */
250 	public void setValue(double value)
251 	{
252 		super.setDoubleValue(value);
253 	}
254 
255 	/* (non-Javadoc)
256 	 * @see com.cosylab.gui.displayers.DoubleDisplayer#getValue()
257 	 */
258 	public double getValue()
259 	{
260 		return super.getDoubleValue();
261 	}
262 
263 	/**
264 	 * Accepts only consumers, which support
265 	 * <code>NonblockingNumberConsumer</code> which is used for receiving
266 	 * updates from user.
267 	 *
268 	 * @see com.cosylab.gui.displayers.DataSource#addConsumer(com.cosylab.gui.displayers.DataConsumer)
269 	 */
270 	public void addConsumer(DataConsumer consumer) throws PropertyVetoException
271 	{
272 		if (consumer == null) {
273 			throw new NullPointerException("consumer");
274 		}
275 
276 		NonblockingNumberConsumer c = (NonblockingNumberConsumer)consumer
277 			.getDataConsumer(NonblockingNumberConsumer.class);
278 
279 		if (c == null) {
280 			throw new PropertyVetoException("Consumer '" + consumer
281 			    + "' must support NonblockingNumberConsumer.", null);
282 		}
283 
284 		support.addConsumer(c);
285 	}
286 
287 	/* (non-Javadoc)
288 	 * @see com.cosylab.gui.displayers.CommonDisplayer#cleanup()
289 	 */
290 	public void cleanup()
291 	{
292 		internalCleanup();
293 		updateDataState(new DataState(DataState.NOT_INITIALIZED));
294 	}
295 
296 	/* (non-Javadoc)
297 	 * @see com.cosylab.gui.core.CosyComponent#destroy()
298 	 */
299 	public void destroy()
300 	{
301 		cleanup();
302 		support.removeAllConsumers();
303 		dataState = null;
304 	}
305 
306 	/* (non-Javadoc)
307 	 * @see com.cosylab.gui.displayers.DataSource#removeConsumer(com.cosylab.gui.displayers.DataConsumer)
308 	 */
309 	public void removeConsumer(DataConsumer consumer)
310 	{
311 		support.removeConsumer(consumer);
312 	}
313 
314 	/* (non-Javadoc)
315 	 * @see com.cosylab.gui.displayers.CommonDisplayer#resume()
316 	 */
317 	public void resume()
318 	{
319 		if (suspendCount > 0) {
320 			suspendCount--;
321 		}
322 
323 		if (suspendCount == 0) {
324 			setEnabled(true);
325 		}
326 	}
327 
328 	/* (non-Javadoc)
329 	 * @see com.cosylab.gui.displayers.CommonDisplayer#suspend()
330 	 */
331 	public void suspend()
332 	{
333 		setEnabled(false);
334 		suspendCount++;
335 	}
336 
337 	/* (non-Javadoc)
338 	 * @see com.cosylab.gui.displayers.DataConsumer#updateDataState(com.cosylab.gui.displayers.DataState)
339 	 */
340 	public void updateDataState(DataState state)
341 	{
342 		DataState old = dataState;
343 		dataState = state;
344 		firePropertyChange(DATA_STATE, old, dataState);
345 	}
346 
347 	/* (non-Javadoc)
348 	 * @see com.cosylab.gui.displayers.DoubleConsumer#updateValue(long, double)
349 	 */
350 	public void updateValue(long timestamp, double value)
351 	{
352 		setValue(value);
353 	}
354 
355 	private void initialize()
356 	{
357 		setNumberType(double.class);
358 
359 		// adds set listener, which fires data source updates
360 		addSetListener(new SetListener() {
361 				public void setPerformed(SetEvent e)
362 				{
363 					try {
364 						double value = e.getDoubleValue();
365 
366 						DataConsumer[] d = getConsumers();
367 						
368 						for (int i = 0; i < d.length; i++) {
369 							NonblockingNumberConsumer dd = (NonblockingNumberConsumer)d[i];
370 							
371 							if (dd != null) {
372 								dd.updateNonblocking(new Double(value));
373 						
374 							}
375 						}
376 					} catch (Exception ex) {
377 						ex.printStackTrace();
378 					}
379 				}
380 			});
381 		setMaximum(100);
382 		setMinimum(0);
383 		setEditable(true);
384 		setLayoutOrientation(AbstractDisplayerPanel.DYNAMIC_LAYOUT);
385 		setBoundsVisible(false);
386 		setTiltingEnabled(true);
387 		setColumns(5);		
388 		setWarnOutOfBounds(true);
389 		setPopupEnabled(true);
390 	}
391 
392 	private void internalCleanup()
393 	{
394 		setEnhanced(true);
395 		setResizable(true);
396 		setMaximum(100);
397 		setMinimum(0);
398 		setValue(0);
399 		setTitle("Double Number Field");
400 		setUnits(null);
401 		setFormat(null);
402 		setLayoutOrientation(AbstractDisplayerPanel.DYNAMIC_LAYOUT);
403 		setBoundsVisible(false);
404 		setUnitsVisible(true);
405 		setTitleVisible(true);
406 		setEditable(true);
407 		setTiltingEnabled(true);
408 		setColumns(5);
409 	}
410 
411 	/* (non-Javadoc)
412 	 * @see com.cosylab.gui.displayers.DataConsumer#getSupportedConsumerTypes()
413 	 */
414 	@SuppressWarnings("unchecked")
415 	public Class[] getSupportedConsumerTypes()
416 	{
417 		return DoubleConsumerMulticaster.PREFERED_CONSUMER_TYPES;
418 	}
419 
420 	/* (non-Javadoc)
421 	 * @see com.cosylab.gui.displayers.Displayer#getDataSource()
422 	 */
423 	public DataSource getDataSource()
424 	{
425 		return dataSource;
426 	}
427 
428 	/* (non-Javadoc)
429 	 * @see com.cosylab.gui.displayers.Displayer#setDataSource(com.cosylab.gui.displayers.DataSource)
430 	 */
431 	public void setDataSource(DataSource dataSource)
432 		throws PropertyVetoException
433 	{
434 		DisplayerUtilities.prepareNewDataSource(dataSource,this);
435 		
436 		DataSource old= this.dataSource;
437 		this.dataSource = dataSource;
438 		
439 		firePropertyChange(DATA_SOURCE,old,dataSource);
440 	}
441 
442 	
443 	/**
444 	 * Returns the converter.
445 	 * @return Returns the converter.
446 	 */
447 	public Converter getConverter() {
448 		return converter;
449 	}
450 
451 	
452 	/**
453 	 * Sets new converter.
454 	 * @param converter The converter to set.
455 	 * @throws PropertyVetoException if set fails
456 	 */
457 	public void setConverter(Converter converter) throws PropertyVetoException {
458 		if (this.converter != null && this.converter.equals(converter) ||
459 				(this.converter == null && converter == null)) return;
460 		DisplayerUtilities.prepareNewConverter(converter,this);
461 		
462 		Converter old= this.converter;
463 		this.converter = converter;
464 		
465 		firePropertyChange(CONVERTER_PROPERTY,old,this.converter);
466 	}
467 
468 	/* (non-Javadoc)
469 	 * @see com.cosylab.gui.displayers.DataSource#removeAllConsumers()
470 	 */
471 	public void removeAllConsumers()
472 	{
473 		support.removeAllConsumers();
474 	}
475 	
476 	public InfoDialog getInfoDialog() {
477 		if (infoDialog == null) {
478 			infoDialog = new InfoDialog(this);
479 		}
480 		return infoDialog;
481 	}
482 	
483 	public PopupManager getPopupManager()
484 	{
485 		if (popupManager == null) {
486 			popupManager = super.getPopupManager();
487 			popupManager.addAction(new AbstractAction("Info...") {
488 				private static final long serialVersionUID = 1L;
489 
490 					public void actionPerformed(ActionEvent e)
491 					{
492 						getInfoDialog().setVisible(true);
493 					}
494 				});
495 		}
496 		
497 		return popupManager;
498 	}
499 }
500 
501 /* __oOo__ */