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.displayers;
21  
22  import java.beans.PropertyVetoException;
23  import java.lang.reflect.InvocationTargetException;
24  import java.util.ArrayList;
25  import java.util.BitSet;
26  import java.util.Map;
27  
28  import javax.swing.JComponent;
29  
30  import com.cosylab.gui.adapters.Converter;
31  import com.cosylab.gui.util.UserSettingsProtection;
32  import com.cosylab.util.BitCondition;
33  
34  /**
35   * <code>DisplayerUtilities</code> contains set of usefull methods and fields
36   * which help to implement various <code>Displayer</code> interfaces.
37   *
38   * @author <a href="mailto:igor.kriznar@cosylab.com">Igor Kriznar</a>
39   * @version $Id: DisplayerUtilities.java,v 1.19 2008-04-22 12:31:02 jbobnar Exp $
40   *
41   * @since Dec 3, 2003.
42   */
43  public final class DisplayerUtilities
44  {
45  	private final static boolean debug = false;
46  
47  	/**
48  	 * List of commonly supporter characteristics for numeric displayers
49  	 * (double, long).
50  	 */
51  	public static final String[] COMMON_NUMERIC_DISPLAYER_CHARACTERISTICS = {
52  			CommonDisplayer.C_MINIMUM, CommonDisplayer.C_MAXIMUM,
53  			CommonDisplayer.C_FORMAT, CommonDisplayer.C_UNITS,
54  			CommonDisplayer.C_DISPLAY_NAME, Displayer.C_EDITABLE
55  		};
56  
57  	/**
58  	 * List of commonly supported Java Bean properties for numeric displayers
59  	 * (double, long).
60  	 */
61  	public static final String[] COMMON_NUMERIC_DISPLAYER_PROPERTIES= {
62  		CommonDisplayer.C_MINIMUM, CommonDisplayer.C_MAXIMUM,
63  		CommonDisplayer.C_FORMAT, CommonDisplayer.C_UNITS,
64  		"title", Displayer.C_EDITABLE
65  	};
66  
67  	/**
68  	 * List of commonly supporter characteristics for numeric displayers
69  	 * (double, long).
70  	 */
71  	public static final String[] PATTERN_DISPLAYER_CHARACTERISTICS = {
72  		CommonDisplayer.C_DISPLAY_NAME,
73  		CommonDisplayer.C_BIT_DESCRIPTIONS,
74  		CommonDisplayer.C_BIT_MASK,
75  		CommonDisplayer.C_CONDITION_WHEN_CLEARED,
76  		CommonDisplayer.C_CONDITION_WHEN_SET
77  		};
78  
79  	/** List of commonly supporter characteristics for object displayer. */
80  	public static final String[] COMMON_OBJECT_DISPLAYER_CHARACTERISTICS = {  };
81  
82  	/**
83  	 * Combines two arrays of characteristics names in to one.
84  	 *
85  	 * @param char1 array to be combined
86  	 * @param char2 array to be combined
87  	 *
88  	 * @return conbined array of characteristic names
89  	 */
90  	public static final String[] combineCharacteristics(String[] char1,
91  	    String[] char2)
92  	{
93  		ArrayList<String> l = new ArrayList<String>((char1 != null ? char1.length : 0)
94  			    + (char2 != null ? char2.length : 0));
95  
96  		if (char1 != null) {
97  			for (int i = 0; i < char1.length; i++) {
98  				l.add(char1[i]);
99  			}
100 		}
101 
102 		if (char2 != null) {
103 			for (int i = 0; i < char2.length; i++) {
104 				l.add(char2[i]);
105 			}
106 		}
107 
108 		return (String[])l.toArray(new String[l.size()]);
109 	}
110 
111 	/**
112 	 * Combines arrays of characteristics names with singe characteristic name
113 	 * in to one.
114 	 *
115 	 * @param char1 array to be combined
116 	 * @param charName characteeristic name to be combined
117 	 *
118 	 * @return conbined array of characteristic names
119 	 */
120 	public static final String[] combineCharacteristics(String[] char1,
121 	    String charName)
122 	{
123 		ArrayList<String> l = new ArrayList<String>((char1 != null ? char1.length : 0)
124 			    + (charName != null ? 1 : 0));
125 
126 		if (char1 != null) {
127 			for (int i = 0; i < char1.length; i++) {
128 				l.add(char1[i]);
129 			}
130 		}
131 
132 		if (charName != null) {
133 			l.add(charName);
134 		}
135 
136 		return (String[])l.toArray(new String[l.size()]);
137 	}
138 
139 	private DisplayerUtilities()
140 	{
141 		super();
142 	}
143 
144 	/**
145 	 * Sets characteristics from <code>Map</code> to the displayer.
146 	 *
147 	 * @param characteristics the Map with characteristics
148 	 * @param disp the displayer to  which characteristics will be set
149 	 * @throws IllegalAccessException 
150 	 * @throws InvocationTargetException 
151 	 * @throws NoSuchMethodException 
152 	 */
153 	public static final void setCharacteristics(Map characteristics,
154 	    DoubleDisplayer disp)
155 	{
156 		if (debug) {
157 			System.out.println("[DispUtilities::setChar] setting to '" + disp
158 			    + "' characteristics " + characteristics);
159 		}
160 
161 		disp.suspend();
162 
163 		Double min = 0.0;
164 		Double max = 1.0;
165 	
166 		Object oMin = characteristics.get(CommonDisplayer.C_MINIMUM);
167 
168 		if (oMin != null) {
169 			min = (((Number)oMin).doubleValue());
170 		}
171 
172 		Object oMax = characteristics.get(CommonDisplayer.C_MAXIMUM);
173 
174 		if (oMax != null) {
175 			max = (((Number)oMax).doubleValue());
176 		}
177 
178 		if (oMax != null && max<disp.getMinimum()) {
179 			if (oMin != null) {
180 				try {
181 					UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MINIMUM,min);
182 				} catch (Exception e) {
183 					e.printStackTrace();
184 				}
185 				disp.setValue(min);
186 			} else {
187 				try {
188 					UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MINIMUM,max);
189 				} catch (Exception e) {
190 					e.printStackTrace();
191 				}
192 				disp.setValue(max);
193 			}
194 				try {
195 					UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MAXIMUM,max);
196 				} catch (Exception e) {
197 					e.printStackTrace();
198 				}
199 		} else if (oMin != null && min>disp.getMaximum()) {
200 			if (oMax != null) {
201 				try {
202 					UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MAXIMUM,max);
203 				} catch (Exception e) {
204 					e.printStackTrace();
205 				}
206 			} else {
207 				try {
208 					UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MAXIMUM,min);
209 				} catch (Exception e) {
210 					e.printStackTrace();
211 				}
212 			}
213 			disp.setValue(min);
214 			try {
215 				UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MINIMUM,min);
216 			} catch (Exception e) {
217 				e.printStackTrace();
218 			}
219 		} else {
220 			if (oMin != null) {
221 				try {
222 					UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MINIMUM,min);
223 				} catch (Exception e) {
224 					e.printStackTrace();
225 				}
226 			}
227 			if (oMax != null) {
228 				try {
229 					UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MAXIMUM,max);
230 				} catch (Exception e) {
231 					e.printStackTrace();
232 				}
233 			}
234 		}
235 		
236 		Object o = characteristics.get(CommonDisplayer.C_FORMAT);
237 
238 		if (o != null) {
239 			try {
240 				UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_FORMAT,o.toString());
241 			} catch (Exception e) {
242 				e.printStackTrace();
243 			}
244 		}
245 
246 		o = characteristics.get(CommonDisplayer.C_UNITS);
247 
248 		if (o != null) {
249 			try {
250 				UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_UNITS,o.toString());
251 			} catch (Exception e) {
252 				e.printStackTrace();
253 			}
254 		}
255 
256 		o = characteristics.get(CommonDisplayer.C_DISPLAY_NAME);
257 
258 		if (o != null) {
259 			try {
260 				UserSettingsProtection.setUnprotected((JComponent)disp,"title",o.toString());
261 			} catch (Exception e) {
262 				e.printStackTrace();
263 			}
264 		}
265 
266 		/* Displayer officially does not support set but by JavaBeans contract
267 		 * some Displayers migth support also setter.*/
268 		o = characteristics.get(Displayer.C_EDITABLE);
269 
270 		if (o != null) {
271 			try {
272 				UserSettingsProtection.setUnprotected((JComponent)disp,"editable",o);
273 			} catch (NoSuchMethodException ex) {
274 				// do nothing
275 			} catch (IllegalAccessException ex) {
276 				ex.printStackTrace();
277 			} catch (InvocationTargetException ex) {
278 				ex.printStackTrace();
279 			}
280 		}
281 
282 		disp.resume();
283 
284 		if (debug) {
285 			System.out.println("[DispUtilities::setChar] test: min= "
286 			    + disp.getMinimum() + " max= " + disp.getMaximum() + " title= "
287 			    + disp.getTitle());
288 		}
289 	}
290 
291 	/**
292 	 * Sets characteristics from <code>Map</code> to the displayer.
293 	 *
294 	 * @param characteristics the Map with characteristics
295 	 * @param disp the displayer to  which characteristics will be set
296 	 * @throws IllegalAccessException 
297 	 * @throws InvocationTargetException 
298 	 * @throws NoSuchMethodException 
299 	 */
300 	public static final void setCharacteristics(Map characteristics,
301 	    LongDisplayer disp)
302 	{
303 		if (debug) {
304 			System.out.println("[DispUtilities::setChar] setting to '" + disp
305 			    + "' characteristics " + characteristics);
306 		}
307 
308 		disp.suspend();
309 
310 		long min = 0;
311 		long max = 1;
312 		
313 		Object oMin = characteristics.get(CommonDisplayer.C_MINIMUM);
314 
315 		if (oMin != null) {
316 			min = (((Number)oMin).longValue());
317 		}
318 
319 		Object oMax = characteristics.get(CommonDisplayer.C_MAXIMUM);
320 
321 		if (oMax != null) {
322 			max = (((Number)oMax).longValue());
323 		}
324 
325 		if (oMax != null && max<disp.getMinimum()) {
326 			if (oMin != null) {
327 				try {
328 					UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MINIMUM,min);
329 				} catch (Exception e) {
330 					e.printStackTrace();
331 				}
332 				disp.setValue(min);
333 			} else {
334 				try {
335 					UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MINIMUM,max);
336 				} catch (Exception e) {
337 					e.printStackTrace();
338 				}
339 				disp.setValue(max);
340 			}
341 			try {
342 				UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MAXIMUM,max);
343 			} catch (Exception e) {
344 				e.printStackTrace();
345 			}
346 		} else if (oMin != null && min>disp.getMaximum()) {
347 			if (oMax != null) {
348 				try {
349 					UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MAXIMUM,max);
350 				} catch (Exception e) {
351 					e.printStackTrace();
352 				}
353 			} else {
354 				try {
355 					UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MAXIMUM,min);
356 				} catch (Exception e) {
357 					e.printStackTrace();
358 				}
359 			}
360 			disp.setValue(min);
361 			try {
362 				UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MINIMUM,min);
363 			} catch (Exception e) {
364 				e.printStackTrace();
365 			}
366 		} else {
367 			if (oMin != null) {
368 				try {
369 					UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MINIMUM,min);
370 				} catch (Exception e) {
371 					e.printStackTrace();
372 				}
373 			}
374 			if (oMax != null) {
375 				try {
376 					UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_MAXIMUM,max);
377 				} catch (Exception e) {
378 					e.printStackTrace();
379 				}
380 			}
381 		}
382 		
383 		Object o = characteristics.get(CommonDisplayer.C_FORMAT);
384 
385 		if (o != null) {
386 			try {
387 				UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_FORMAT,o.toString());
388 			} catch (Exception e) {
389 				e.printStackTrace();
390 			}
391 		}
392 
393 		o = characteristics.get(CommonDisplayer.C_UNITS);
394 
395 		if (o != null) {
396 			try {
397 				UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_UNITS,o.toString());
398 			} catch (Exception e) {
399 				e.printStackTrace();
400 			}
401 		}
402 
403 		o = characteristics.get(CommonDisplayer.C_DISPLAY_NAME);
404 
405 		if (o != null) {
406 			try {
407 				UserSettingsProtection.setUnprotected((JComponent)disp,"title",o.toString());
408 			} catch (Exception e) {
409 				e.printStackTrace();
410 			}
411 		}
412 
413 		/* Displayer officially does not support set but by JavaBeans contract
414 		 * some Displayers migth support also setter.*/
415 		o = characteristics.get(Displayer.C_EDITABLE);
416 
417 		if (o != null) {
418 			try {
419 				UserSettingsProtection.setUnprotected((JComponent)disp,"editable",o);
420 			} catch (NoSuchMethodException ex) {
421 				// do nothing
422 			} catch (IllegalAccessException ex) {
423 				ex.printStackTrace();
424 			} catch (InvocationTargetException ex) {
425 				ex.printStackTrace();
426 			}
427 		}
428 
429 		disp.resume();
430 
431 		if (debug) {
432 			System.out.println("[DispUtilities::setChar] test: min= "
433 			    + disp.getMinimum() + " max= " + disp.getMaximum() + " title= "
434 			    + disp.getTitle());
435 		}
436 	}
437 
438 	/**
439 	 * Sets characteristics from <code>Map</code> to the displayer.
440 	 *
441 	 * @param characteristics the Map with characteristics
442 	 * @param disp the displayer to  which characteristics will be set
443 	 * @throws IllegalAccessException 
444 	 * @throws InvocationTargetException 
445 	 * @throws NoSuchMethodException 
446 	 */
447 	public static final void setCharacteristics(Map characteristics,
448 	    PatternDisplayer disp)
449 	{
450 		if (debug) {
451 			System.out.println("[DispUtilities::setChar] setting to '" + disp
452 			    + "' characteristics " + characteristics);
453 		}
454 
455 		disp.suspend();
456 
457 		Object o = characteristics.get(CommonDisplayer.C_FORMAT);
458 
459 		if (o != null) {
460 			try {
461 				UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_FORMAT,o.toString());
462 			} catch (Exception e) {
463 				e.printStackTrace();
464 			}
465 		}
466 
467 		o = characteristics.get(CommonDisplayer.C_UNITS);
468 
469 		if (o != null) {
470 			try {
471 				UserSettingsProtection.setUnprotected((JComponent)disp,CommonDisplayer.C_UNITS,o.toString());
472 			} catch (Exception e) {
473 				e.printStackTrace();
474 			}
475 		}
476 
477 		o = characteristics.get(CommonDisplayer.C_DISPLAY_NAME);
478 
479 		if (o != null) {
480 			try {
481 				UserSettingsProtection.setUnprotected((JComponent)disp,"title",o.toString());
482 			} catch (Exception e) {
483 				e.printStackTrace();
484 			}
485 		}
486 
487 		/* Displayer officially does not support set but by JavaBeans contract
488 		 * some Displayers migth support also setter.*/
489 		o = characteristics.get(Displayer.C_EDITABLE);
490 
491 		if (o != null) {
492 			try {
493 				UserSettingsProtection.setUnprotected((JComponent)disp,"editable",o);
494 			} catch (NoSuchMethodException ex) {
495 				// do nothing
496 			} catch (IllegalAccessException ex) {
497 				ex.printStackTrace();
498 			} catch (InvocationTargetException ex) {
499 				ex.printStackTrace();
500 			}
501 		}
502 
503 		o = characteristics.get(CommonDisplayer.C_BIT_MASK);
504 
505 		if (o != null) {
506 			try {
507 				UserSettingsProtection.setUnprotected((JComponent)disp,"bitMask",(BitSet)o);
508 			} catch (Exception e) {
509 				e.printStackTrace();
510 			}
511 		}
512 
513 		o = characteristics.get(CommonDisplayer.C_CONDITION_WHEN_CLEARED);
514 
515 		if (o != null) {
516 			try {
517 				UserSettingsProtection.setUnprotected((JComponent)disp,"conditionWhenCleared",(BitCondition[])o);
518 			} catch (Exception e) {
519 				e.printStackTrace();
520 			}
521 		}
522 
523 		o = characteristics.get(CommonDisplayer.C_CONDITION_WHEN_SET);
524 
525 		if (o != null) {
526 			try {
527 				UserSettingsProtection.setUnprotected((JComponent)disp,"conditionWhenSet",(BitCondition[])o);
528 			} catch (Exception e) {
529 				e.printStackTrace();
530 			}
531 		}
532 
533 		o = characteristics.get(CommonDisplayer.C_BIT_DESCRIPTIONS);
534 
535 		if (o != null) {
536 			try {
537 				UserSettingsProtection.setUnprotected((JComponent)disp,"bitDescriptions",(String[])o);
538 			} catch (Exception e) {
539 				e.printStackTrace();
540 			}
541 		}
542 
543 		disp.resume();
544 	}
545 
546 	/**
547 	 * Trys to transform double format string to long format string.
548 	 *
549 	 * @param format double prinf format string
550 	 *
551 	 * @return possibly safer long compatible format string
552 	 */
553 	public static String toLongFormat(String format)
554 	{
555 		if (format != null && (format.indexOf('f') > -1)) {
556 			format = format.replace('f', 'd');
557 
558 			int dot = format.indexOf('.');
559 
560 			if (dot > -1) {
561 				format = format.substring(0, dot)
562 					+ format.substring(format.indexOf('d'));
563 			}
564 		}
565 
566 		return format;
567 	}
568 	
569 	/**
570 	 * This method can be used from <code>setConverter()</code> method from convertible displayer, which
571 	 * is passed as parameter. This method must be called before new converter was 
572 	 * stored in local field and after this method new converter must be stored in local field. 
573 	 * 
574 	 * @param converter new converter to be set to displayer
575 	 * @param disp displayer which receives new converter
576 	 * @throws PropertyVetoException 
577 	 */
578 	public static void prepareNewConverter(Converter converter, ConvertibleDisplayer disp) throws PropertyVetoException {
579 		reattachDataTransport(disp.getConverter(), converter, disp.getDataSource(), disp.getDataSource(), disp);
580 	}
581 
582 	/**
583 	 * @param oldConverter
584 	 * @param newConverter
585 	 * @param oldDataSource
586 	 * @param displayer
587 	 * @throws PropertyVetoException
588 	 */
589 	private static void reattachDataTransport(Converter oldConverter, Converter newConverter, DataSource oldDataSource, DataSource newDataSource, Displayer displayer) throws PropertyVetoException {
590 		// Unregister old datasource
591 		if (oldDataSource!=null) {
592 			oldDataSource.removeConsumer(displayer);
593 			if (oldConverter!=null) {
594 				oldDataSource.removeConsumer(oldConverter);
595 			}
596 		}
597 		// Unregister old converter
598 		if (oldConverter!=null) {
599 			oldConverter.removeConsumer(displayer);
600 		}
601 
602 		// register new converter
603 		if (newDataSource!=null) {
604 			if (newConverter!=null) {
605 				// insert new converter betwean displayer and datasource 
606 				newConverter.addConsumer(displayer);
607 				newDataSource.addConsumer(newConverter);
608 			} else {
609 				// there is no new converter, reattach dispalyer to datasource
610 				newDataSource.addConsumer(displayer);
611 			}
612 		}
613 	}
614 	
615 	/**
616 	 * This method can be used from <code>setDataSource()</code> method from displayer, which
617 	 * is passed as parameter. This method must be called before new datasource was 
618 	 * stored in local field and after this method new datasource must be stored in local field. 
619 	 * 
620 	 * @param dataSource new datasource to be set to displayer
621 	 * @param disp displayer which receives new converter
622 	 * @throws PropertyVetoException 
623 	 */
624 	public static void prepareNewDataSource(DataSource dataSource, ConvertibleDisplayer disp) throws PropertyVetoException {
625 		reattachDataTransport(disp.getConverter(), disp.getConverter(), disp.getDataSource(), dataSource, disp);
626 	}
627 
628 	/**
629 	 * This method can be used from <code>setDataSource()</code> method from displayer, which
630 	 * is passed as parameter. This method must be called before new datasource was 
631 	 * stored in local field and after this method new datasource must be stored in local field. 
632 	 * 
633 	 * @param dataSource new datasource to be set to displayer
634 	 * @param disp displayer which receives new converter
635 	 * @throws PropertyVetoException 
636 	 */
637 	public static void prepareNewDataSource(DataSource dataSource, Displayer disp) throws PropertyVetoException {
638 		reattachDataTransport(null, null, disp.getDataSource(), dataSource, disp);
639 	}
640 	
641 	/**
642 	 * Extracts single value from an array. If index is over array size, then returns 
643 	 * value from index position closest to requested index.
644 	 * 
645 	 * @param index an index of value to return
646 	 * @param array source array
647 	 * @return value at specified index if valud or closes valid index
648 	 */
649 	public static double extract(int index, double[] array) {
650 		if (index<0) {
651 			return array[0];
652 		}
653 		if (index>=array.length) {
654 			return array[array.length-1];
655 		}
656 		return array[index];
657 	}
658 	
659 	/**
660 	 * Extracts single value from an array. If index is over array size, then returns 
661 	 * value from index position closest to requested index.
662 	 * 
663 	 * @param index an index of value to return
664 	 * @param array source array
665 	 * @return value at specified index if valud or closes valid index
666 	 */
667 	public static String extract(int index, String[] array) {
668 		if (index<0) {
669 			return array[0];
670 		}
671 		if (index>array.length) {
672 			return array[array.length];
673 		}
674 		return array[index];
675 	}
676 	
677 	/**
678 	 * Converts the array to string. This method is used displayer to transform
679 	 * a sequence to string.
680 	 * 
681 	 * @param value
682 	 * @return
683 	 */
684 	public static String toString(Object[] value) {
685 		StringBuilder s= new StringBuilder(16*value.length);
686 		s.append('[');
687 		if (value.length>0) {
688 			s.append(value[0]);
689 		}
690 		for (int i = 1; i < value.length; i++) {
691 			s.append(',');
692 			s.append(value[i]);
693 		}
694 		s.append(']');
695 		return s.toString();
696 	}
697 
698 }
699 
700 /* __oOo__ */