1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.cosylab.gui;
21
22 import java.awt.BorderLayout;
23 import java.awt.event.ActionEvent;
24 import java.awt.event.ActionListener;
25 import java.beans.PropertyVetoException;
26 import java.util.Map;
27
28 import javax.swing.AbstractAction;
29 import javax.swing.JButton;
30 import javax.swing.JFrame;
31
32 import com.cosylab.events.SetEvent;
33 import com.cosylab.events.SetListener;
34 import com.cosylab.gui.adapters.Converter;
35 import com.cosylab.gui.components.Slider;
36 import com.cosylab.gui.components.util.PopupManager;
37 import com.cosylab.gui.displayers.ConvertibleDisplayer;
38 import com.cosylab.gui.displayers.DataConsumer;
39 import com.cosylab.gui.displayers.DataSource;
40 import com.cosylab.gui.displayers.DataSourceSupport;
41 import com.cosylab.gui.displayers.DataState;
42 import com.cosylab.gui.displayers.DisplayerUtilities;
43 import com.cosylab.gui.displayers.DoubleConsumer;
44 import com.cosylab.gui.displayers.DoubleConsumerMulticaster;
45 import com.cosylab.gui.displayers.DoubleDisplayer;
46 import com.cosylab.gui.displayers.NonblockingNumberConsumer;
47 import com.cosylab.util.CommonException;
48
49
50
51
52
53
54
55
56 public class SliderDisplayer extends Slider implements DoubleDisplayer,
57 DataSource, ConvertibleDisplayer
58 {
59 private static final long serialVersionUID = 1L;
60 @SuppressWarnings("unchecked")
61 private DataSourceSupport support = new DataSourceSupport(new Class[]{
62 NonblockingNumberConsumer.class
63 });
64 private DataState dataState = new DataState(DataState.UNDEFINED);
65 private boolean newUpdate = false;
66 private DataSource dataSource;
67 private double lastValue = 0;
68 private InfoDialog infoDialog;
69 private PopupManager popupManager;
70
71 private int suspendCount = 0;
72
73
74
75
76 public SliderDisplayer()
77 {
78 super();
79 initializeDisplayer();
80 }
81
82
83
84
85 @SuppressWarnings("unchecked")
86 public Class[] getAcceptableConsumerTypes()
87 {
88 return support.getAcceptableConsumerTypes();
89 }
90
91
92
93
94 public void setCharacteristics(Map characteristics)
95 {
96 if (characteristics == null) {
97 throw new NullPointerException("characteristics");
98 }
99
100 newUpdate = true;
101
102 DisplayerUtilities.setCharacteristics(characteristics, this);
103 }
104
105
106
107
108 public DataConsumer[] getConsumers()
109 {
110 return support.getConsumers();
111 }
112
113
114
115
116 public DataConsumer getDataConsumer(Class type)
117 {
118 if (type == DoubleConsumer.class) {
119 return this;
120 }
121
122 return DoubleConsumerMulticaster.createDataConsumer(type, this);
123 }
124
125
126
127
128 public DataState getDataState()
129 {
130 return dataState;
131 }
132
133
134
135
136 public DataConsumer getDefaultDataConsumer()
137 {
138 return this;
139 }
140
141
142
143
144 public String[] getSupportedCharacteristics()
145 {
146 return DisplayerUtilities.COMMON_NUMERIC_DISPLAYER_CHARACTERISTICS;
147 }
148
149
150
151
152 @SuppressWarnings("unchecked")
153 public Class[] getSupportedConsumerTypes()
154 {
155 return DoubleConsumerMulticaster.PREFERED_CONSUMER_TYPES;
156 }
157
158
159
160
161
162
163
164
165 public void addConsumer(DataConsumer consumer) throws PropertyVetoException
166 {
167 if (consumer == null) {
168 throw new NullPointerException("consumer");
169 }
170
171 NonblockingNumberConsumer c = (NonblockingNumberConsumer)consumer
172 .getDataConsumer(NonblockingNumberConsumer.class);
173
174 if (c == null) {
175 throw new PropertyVetoException("Consumer '" + consumer
176 + "' must support NonblockingNumberConsumer.", null);
177 }
178
179 support.addConsumer(c);
180 }
181
182
183
184
185 public void cleanup()
186 {
187 internalCleanup();
188 updateDataState(new DataState(DataState.NOT_INITIALIZED));
189 }
190
191
192
193
194 public void destroy()
195 {
196 cleanup();
197 support.removeAllConsumers();
198 dataState = null;
199 }
200
201
202
203
204 public void removeConsumer(DataConsumer consumer)
205 {
206 support.removeConsumer(consumer);
207 }
208
209
210
211
212
213 public boolean isSuspended()
214 {
215 return (suspendCount > 0);
216 }
217
218
219
220
221
222 public void resume()
223 {
224 if (suspendCount > 0) {
225 suspendCount--;
226 }
227
228 if (suspendCount == 0) {
229 setEnabled(true);
230 setReadback(lastValue);
231
232 if (newUpdate) {
233 synchronize();
234 newUpdate = false;
235 }
236 }
237 }
238
239
240
241
242
243 public void suspend()
244 {
245 setEnabled(false);
246 suspendCount++;
247 }
248
249
250
251
252 public void updateDataState(DataState state)
253 {
254 DataState old = dataState;
255 dataState = state;
256 firePropertyChange(DATA_STATE, old, dataState);
257 }
258
259 protected short update = 0;
260 private Converter converter;
261
262
263
264
265 public void updateValue(long timestamp, double value)
266 throws CommonException
267 {
268 lastValue = value;
269
270
271 if (!isSuspended()) {
272 setReadback(value);
273
274 if (newUpdate) {
275 synchronize();
276 newUpdate = false;
277 }
278
279 if (update < 2) {
280 synchronize();
281 update++;
282 }
283
284 }
285
286 }
287
288 private void initializeDisplayer()
289 {
290 addSetListener(new SetListener() {
291 public void setPerformed(SetEvent e)
292 {
293 try {
294 double value = e.getDoubleValue();
295
296 DataConsumer[] d = getConsumers();
297
298 for (int i = 0; i < d.length; i++) {
299 NonblockingNumberConsumer dd = (NonblockingNumberConsumer)d[i];
300
301 if (dd != null) {
302 dd.updateNonblocking(new Double(value));
303 }
304 }
305 } catch (Exception ex) {
306 ex.printStackTrace();
307 }
308 }
309 });
310 setPopupEnabled(true);
311 internalCleanup();
312 }
313
314 private void internalCleanup()
315 {
316 setMinimum(0);
317 setMaximum(100);
318 setValue(0);
319 setTitle("Slider");
320 setUnits(null);
321 setUnitsVisible(true);
322 setFormat("%3.2f");
323 setEditable(true);
324 }
325
326
327
328
329 public DataSource getDataSource()
330 {
331 return dataSource;
332 }
333
334
335
336
337 public void setDataSource(DataSource dataSource)
338 throws PropertyVetoException
339 {
340 DisplayerUtilities.prepareNewDataSource(dataSource,this);
341
342 DataSource old= this.dataSource;
343 this.dataSource = dataSource;
344
345 firePropertyChange(DATA_SOURCE,old,dataSource);
346 }
347
348
349
350
351
352 public Converter getConverter() {
353 return converter;
354 }
355
356
357
358
359
360 public void setConverter(Converter converter) throws PropertyVetoException {
361 if (this.converter != null && this.converter.equals(converter) ||
362 (this.converter == null && converter == null)) return;
363 DisplayerUtilities.prepareNewConverter(converter,this);
364
365 Converter old= this.converter;
366 this.converter = converter;
367
368 firePropertyChange(CONVERTER_PROPERTY,old,this.converter);
369 }
370
371
372
373
374 public void removeAllConsumers()
375 {
376 support.removeAllConsumers();
377 }
378
379
380
381
382
383
384 public InfoDialog getInfoDialog() {
385 if (infoDialog == null) {
386 infoDialog = new InfoDialog(this);
387 }
388 return infoDialog;
389 }
390
391
392
393
394
395 public PopupManager getPopupManager()
396 {
397 if (popupManager == null) {
398 popupManager = super.getPopupManager();
399 popupManager.addAction(new AbstractAction("Info...") {
400 private static final long serialVersionUID = 1L;
401
402 public void actionPerformed(ActionEvent e)
403 {
404 getInfoDialog().setVisible(true);
405 }
406 });
407 }
408
409 return popupManager;
410 }
411
412 public static void main(String[] args)
413 {
414 JFrame f = new JFrame();
415 f.getContentPane().setLayout(new BorderLayout());
416 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
417
418 final SliderDisplayer s = new SliderDisplayer();
419 f.getContentPane().add(s, BorderLayout.SOUTH);
420
421 JButton b = new JButton("S/R");
422 f.getContentPane().add(b, BorderLayout.EAST);
423 b.addActionListener(new ActionListener() {
424 public void actionPerformed(ActionEvent e)
425 {
426 if (s.isSuspended()) {
427 s.resume();
428 } else {
429 s.suspend();
430 }
431 }
432 });
433 f.show();
434 }
435
436 }
437
438