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.BorderLayout;
23  import java.awt.Color;
24  import java.awt.Dimension;
25  import java.awt.Image;
26  import java.awt.event.ActionEvent;
27  import java.awt.event.ComponentAdapter;
28  import java.awt.event.ComponentEvent;
29  import java.io.File;
30  import java.util.HashMap;
31  import java.util.Iterator;
32  import java.util.Map;
33  
34  import javax.swing.AbstractAction;
35  import javax.swing.Icon;
36  import javax.swing.ImageIcon;
37  import javax.swing.JLabel;
38  import javax.swing.SwingConstants;
39  
40  import com.cosylab.gui.components.util.ColorHelper;
41  import com.cosylab.gui.components.util.IconHelper;
42  import com.cosylab.gui.components.util.PopupManager;
43  import com.cosylab.gui.components.util.RunnerHelper;
44  import com.cosylab.gui.displayers.AbstractDisplayerPanel;
45  import com.cosylab.gui.displayers.CommonDisplayer;
46  import com.cosylab.gui.displayers.DataConsumer;
47  import com.cosylab.gui.displayers.LongConsumerMulticaster;
48  import com.cosylab.gui.util.UserSettingsProtection;
49  import com.cosylab.util.CommonException;
50  
51  /** 
52   * <code>IconDisplayer</code> is a displayer that displays icons associated with
53   * different values. 
54   * 
55   * 
56   * @author Jaka Bobnar, Cosylab
57   * 
58   */
59  public class IconDisplayer extends AbstractDisplayerPanel implements
60          com.cosylab.gui.displayers.IconDisplayer {
61  	
62  	public static final String ICONS_PROPERTY = "icons";
63  	public static final String DEFAULT_ICON_PROPERTY = "defaultIcon";
64  	public static final String DEFAULT_ICON_NAME_PROPERTY = "defaultIconName";
65  
66  	private static final long serialVersionUID = 1L;
67  
68  	private JLabel label;
69  
70  	private Icon defaultIcon;
71  	private String defaultIconName;
72  	private long value;
73  	private PopupManager popupManager;
74  	private InfoDialog infoDialog;
75  	private boolean keepRatio = false;
76  	private boolean scaleIcons = false;
77  	
78  	private Map<Long, ValueIconPair> valueIcons;
79  
80  	/**
81       * Creates new IconDisplayer.
82       */
83  	public IconDisplayer() {
84  		super();
85  		initialize();
86  	}
87  
88  	/**
89       * Creates new IconDisplayer and defines the default icon.
90       * 
91       * @param defaultIcon
92       *        Default icon to set.
93       */
94  	public IconDisplayer(Icon defaultIcon) {
95  		super();
96  		this.defaultIcon=defaultIcon;
97  		defaultIconName = defaultIcon.toString();
98  		initialize();
99  	}
100 
101 	/**
102      * Creates new IconDisplayer and new default icon. This constructor will
103      * create a new icon from the given path. The path has to be in the classpath
104      * of the project for the icon to be generated. If the path points to an explicit
105      * file in the local system the icon displayer will generate the icon, but will
106      * fail if the file does not exist. 
107      * 
108      * @param defaultIcon the name of default icon in classpath to use
109      */
110 	public IconDisplayer(String defaultIcon) {
111 		this(IconHelper.createIcon(defaultIcon));
112 		defaultIconName = defaultIcon;
113 	}
114 	
115 	/**
116 	 * Creates a new IconDisplayer with the default icon loaded from a given file.
117 	 * This file does not need to be in the classpath of the project.
118 	 * 
119 	 * @param file the icon image file
120 	 */
121 	public IconDisplayer(File file) {
122 		this(IconHelper.createIcon(file));
123 		defaultIconName = file.getAbsolutePath();
124 	}
125 	
126 	/*
127 	 * (non-Javadoc)
128 	 * @see com.cosylab.gui.displayers.IconDisplayer#getLoadedIcons()
129 	 */
130 	public ValueIconPair[] getIcons() {
131 		ValueIconPair[] icons = new ValueIconPair[valueIcons.size()];
132 		Iterator<ValueIconPair> it = valueIcons.values().iterator();
133 		int i = 0;
134 		while (it.hasNext()) {
135 			icons[i] = it.next();
136 			i++;
137 		}
138 		return icons;
139 	
140 	}
141 	
142 	/*
143 	 * (non-Javadoc)
144 	 * @see com.cosylab.gui.displayers.IconDisplayer#setLoadedIcons(java.util.Map)
145 	 */
146 	public void setIcons(ValueIconPair[] icons) {
147    		ValueIconPair[] old = getIcons();
148 		valueIcons.clear();
149 		for (ValueIconPair pair : icons) {
150 			valueIcons.put(pair.getValue(), pair);
151 		}
152 		firePropertyChange(ICONS_PROPERTY, old, getIcons());
153 	}
154 	
155 	/*
156 	 * (non-Javadoc)
157 	 * @see com.cosylab.gui.displayers.IconDisplayer#addIcons(java.util.Map)
158 	 */
159 	public void addIcons(ValueIconPair[] icons) {
160 		ValueIconPair[] old = getIcons();
161 		for (ValueIconPair pair : icons) {
162 			valueIcons.put(pair.getValue(), pair);
163 		}       
164 		firePropertyChange(ICONS_PROPERTY, old, getIcons());
165 	}
166 	
167 	/*
168 	 * (non-Javadoc)
169 	 * @see com.cosylab.gui.displayers.IconDisplayer#removeIcons(com.cosylab.gui.IconValuepair[])
170 	 */
171 	public void removeIcons(ValueIconPair[] icons) {
172 		ValueIconPair[] old = getIcons();
173 		for (ValueIconPair pair : icons) {
174 			valueIcons.remove(pair.getValue());
175 		}   
176 		firePropertyChange(ICONS_PROPERTY, old, getIcons());
177 		
178 	}
179 	
180 	/*
181 	 * (non-Javadoc)
182 	 * @see com.cosylab.gui.displayers.IconDisplayer#removeIcon(com.cosylab.gui.IconValuepair)
183 	 */
184 	public void removeIcon(ValueIconPair icon) {
185 		ValueIconPair[] old = getIcons();
186 		valueIcons.remove(icon.getValue());
187 		firePropertyChange(ICONS_PROPERTY, old, getIcons());
188 	}
189 	 
190 	/**
191 	 * Adds an icon. This method is the same as {@link #addIcon(ValueIconPair)} using
192 	 * the new {@link ValueIconPair}(value, icon).
193 	 * 
194 	 * @param value
195 	 * @param icon
196 	 */
197 	public void addIcon(long value, Icon icon) {
198 		addIcon(new ValueIconPair(value,icon));
199 	}
200 
201 	/*
202 	 * (non-Javadoc)
203 	 * @see com.cosylab.gui.displayers.IconDisplayer#addIcon(com.cosylab.gui.ValueIconPair)
204 	 */
205 	public void addIcon(ValueIconPair pair) {
206 		ValueIconPair[] old = getIcons();
207 		valueIcons.put(pair.getValue(), pair);
208 		firePropertyChange(ICONS_PROPERTY, old, getIcons());
209 	}
210 	
211 	/**
212      * Preforms GUI initialization.
213      */
214 	private void initialize() {
215 
216 		setLayout(new BorderLayout());
217 		add(getTitleLabel(), BorderLayout.NORTH);
218 
219 		
220 		add(getLabel(), BorderLayout.CENTER);
221 		
222 		Dimension size = new Dimension(50, 50);
223 		setPreferredSize(size);
224 		setSize(size); 
225 		setBackground(ColorHelper.getCosyControl());
226 		getLabel().setIcon(getDefaultIcon());
227 		valueIcons = new HashMap<Long, ValueIconPair>();
228 		
229 		setTitleVisible(false);
230 	}
231 	
232 	/*
233 	 * (non-Javadoc)
234 	 * @see com.cosylab.gui.displayers.AbstractDisplayerPanel#setBackground(java.awt.Color)
235 	 */
236 	@Override
237 	public void setBackground(Color bg) {
238 		super.setBackground(bg);
239 		getLabel().setBackground(bg);
240 	}
241 	
242 	/*
243 	 * (non-Javadoc)
244 	 * @see com.cosylab.gui.displayers.AbstractDisplayerPanel#setForeground(java.awt.Color)
245 	 */
246 	@Override
247 	public void setForeground(Color fg) {
248 		super.setForeground(fg);
249 		getLabel().setForeground(fg);
250 	}
251 	
252 	private JLabel getLabel() {
253 		if (label == null) {
254 			label = new JLabel();
255 			label.setHorizontalAlignment(SwingConstants.CENTER);
256 			label.setVerticalAlignment(SwingConstants.CENTER);
257 			label.addComponentListener(new ComponentAdapter() {
258 			
259 				@Override
260 				public void componentResized(ComponentEvent e) {
261 					updateIcon();
262 				}
263 			
264 			});
265 		}
266 		return label;
267 	}
268 
269 	/*
270 	 * (non-Javadoc)
271 	 * @see com.cosylab.gui.displayers.IconDisplayer#setValue(long)
272 	 */
273 	public void setValue(long value) {
274 		this.value = value;
275 		updateIcon();
276 	}
277 	
278 	protected void updateIcon() {
279 		Icon icon = null;
280 		if (valueIcons.get(value) != null) {
281 			icon = valueIcons.get(value).getIcon();
282 		} else {
283 			icon = getDefaultIcon();
284 		}
285 		
286 		if (icon instanceof ImageIcon && scaleIcons) {
287 			if (keepRatio) {
288 				label.setIcon(IconCustomizer.getScaledIcon((ImageIcon)icon, getHeight(), getWidth()));
289 			} else {
290 				label.setIcon(new ImageIcon(((ImageIcon)icon).getImage().
291 						getScaledInstance(getWidth(), getHeight(), Image.SCALE_FAST)));
292 			}
293 		} else {
294 			label.setIcon(icon);
295 		}
296 
297 	}
298 
299 	/*
300 	 * (non-Javadoc)
301 	 * @see com.cosylab.gui.displayers.IconDisplayer#getValue()
302 	 */
303 	public long getValue() {
304 		return value;
305 	}
306 
307 	/**
308      * Creates and sets default icon from file name. Default icon will be used
309      * when no condition is met. The given filename should point to a file inside
310      * the classpath of the project.
311      * 
312      * @param filename
313      */
314 	public void setDefaultIconName(String filename) {
315 		if (filename != null && filename.equals(defaultIconName) || (filename == null && defaultIconName == null)) 
316 			return;
317 		String old = defaultIconName;
318 		setDefaultIcon(IconHelper.createIcon(filename));
319 		defaultIconName = filename;
320 		firePropertyChange(DEFAULT_ICON_NAME_PROPERTY, old, defaultIconName);
321 	}
322 	
323 	/**
324 	 * Creates and sets default icon from the given file. The file can point to
325 	 * any location on the computer as long as it is accessible by the current user's
326 	 * rights.
327 	 * 
328 	 * @param file the image file
329 	 */
330 	public void setDefaultIcon(File file) {
331 		if (file != null && file.getAbsolutePath().equals(defaultIconName) || 
332 				(file == null && defaultIconName == null)) 
333 			return;
334 		String old = defaultIconName;
335 		setDefaultIcon(IconHelper.createIcon(file));
336 		if (file != null) {
337 			defaultIconName = file.getAbsolutePath();
338 		}
339 		firePropertyChange(DEFAULT_ICON_NAME_PROPERTY, old, defaultIconName);
340 	}
341 
342 	/**
343      * Sets default icon. Default icon will be used when no condition is met.
344      * 
345      * @param newIcon
346      *        New icon to use. May be null.
347      */
348 	public void setDefaultIcon(Icon newIcon) {
349 		Icon old = defaultIcon;
350 		defaultIcon = newIcon;
351 		updateIcon();
352 		if (defaultIcon != null)
353 			defaultIconName = defaultIcon.toString();
354 		else 
355 			defaultIconName = null;
356 		firePropertyChange(DEFAULT_ICON_PROPERTY, old, this.defaultIcon);
357 	}
358 	
359 	/**
360 	 * Returns the path to the default icon.
361 	 * 
362 	 * @return
363 	 */
364 	public String getDefaultIconName() {
365 		return defaultIconName;
366 	}
367 
368 	/**
369      * Returns default icon. Default icon is used when no condition is met.
370      * 
371      * @return Instance of default icon or null.
372      */
373 	public Icon getDefaultIcon() {
374 //		if (defaultIcon==null) {
375 //			defaultIcon= new Icon() {
376 //			
377 //				public int getIconHeight() {
378 //					return 32;
379 //				}
380 //			
381 //				public int getIconWidth() {
382 //					return 32;
383 //				}
384 //			
385 //				public void paintIcon(Component c, Graphics g, int x, int y) {
386 //					PaintHelper.paintDisabled(g,4,4,g.getClipBounds().width-8,g.getClipBounds().height-8);
387 //				}
388 //			
389 //			};
390 //		}
391 		return defaultIcon;
392 	}
393 
394 	/*
395      * (non-Javadoc)
396      * 
397      * @see com.cosylab.gui.displayers.Displayer#isEditable()
398      */
399 	public boolean isEditable() {
400 		return false;
401 	}
402 
403 	/*
404      * (non-Javadoc)
405      * 
406      * @see com.cosylab.gui.displayers.LongConsumer#updateValue(long, long)
407      */
408 	public void updateValue(long timestamp, long value) throws CommonException {
409 		setValue(value);
410 	}
411 
412 	/*
413      * (non-Javadoc)
414      * 
415      * @see com.cosylab.gui.displayers.DataConsumer#setCharacteristics(java.util.Map)
416      */
417 	public void setCharacteristics(Map characteristics) {
418 		suspend();
419 		Object o = characteristics.get(CommonDisplayer.C_DISPLAY_NAME);
420 
421 		if (o != null) {
422 			try {
423 				UserSettingsProtection.setUnprotected(this,"title",o.toString());
424 			} catch (Exception e) {
425 				e.printStackTrace();
426 			}
427 		}
428 		resume();
429 	}
430 
431 	/*
432      * (non-Javadoc)
433      * 
434      * @see com.cosylab.gui.displayers.DataConsumer#getSupportedConsumerTypes()
435      */
436 	@SuppressWarnings("unchecked")
437 	public Class[] getSupportedConsumerTypes() {
438 		return LongConsumerMulticaster.SUPPORTED_CONSUMER_TYPES;
439 	}
440 	
441 	/*
442 	 * (non-Javadoc)
443 	 * @see com.cosylab.gui.displayers.DataConsumer#getDataConsumer(java.lang.Class)
444 	 */
445 	@SuppressWarnings("unchecked")
446 	public <D extends DataConsumer> D getDataConsumer(Class<D> type) {
447 		return (D) LongConsumerMulticaster.createDataConsumer(type, this);
448 	}
449 	
450 	/*
451 	 * (non-Javadoc)
452 	 * @see com.cosylab.gui.displayers.AbstractDisplayerPanel#cleanup()
453 	 */
454 	public void cleanup()
455 	{
456 		super.cleanup();
457 		valueIcons.clear();
458 	}
459 	
460 	/**
461 	 * Returns the InfoDialog for this displayer.
462 	 * 
463 	 * @return
464 	 */
465 	public InfoDialog getInfoDialog() {
466 		if (infoDialog == null) {
467 			infoDialog = new InfoDialog(this);
468 		}
469 		return infoDialog;
470 	}
471 	
472 	/*
473 	 * (non-Javadoc)
474 	 * @see com.cosylab.gui.displayers.AbstractDisplayerPanel#getPopupManager()
475 	 */
476 	public PopupManager getPopupManager()
477 	{
478 		if (popupManager == null) {
479 			popupManager = super.getPopupManager();
480 			popupManager.addAction(new AbstractAction("Info...") {
481 				private static final long serialVersionUID = 1L;
482 
483 					public void actionPerformed(ActionEvent e)
484 					{
485 						getInfoDialog().setVisible(true);
486 					}
487 				});
488 		}
489 		
490 		return popupManager;
491 	}
492 	
493 	/**
494 	 * Returns true if icons aspect ratio is kept when the icon is scaled to fit 
495 	 * the component size or false if displayer's aspect ratio is used.
496 	 * 
497 	 * @return true if icons are scaled
498 	 */
499 	public boolean isKeepRatio() {
500 		return keepRatio;
501 	}
502 	
503 	/**
504 	 * Sets whether the icons should keep the aspect ratio if it is scale
505 	 * to fit the component;
506 	 * 
507 	 * @param keepRatio true if aspect ratio of the icons is kept
508 	 */
509 	public void setKeepRatio(boolean keepRatio) {
510 		boolean old= this.keepRatio;
511 		this.keepRatio = keepRatio;
512 		setValue(getValue());
513 		firePropertyChange("keepRatio",old,keepRatio);
514 	}
515 	/**
516 	 * Sets whether the icons should be scale to fit the size of the component.
517 	 * 
518 	 * @param scale true if icons are scaled to fit 
519 	 */
520 	public void setScaleIcons(boolean scale) {
521 		boolean old = scaleIcons;
522 		this.scaleIcons = scale;
523 		setValue(getValue());
524 		firePropertyChange("scaleIcons", old, scaleIcons);
525 	}
526 	
527 	/**
528 	 * Returns true if icons are scaled to fit the size of the component.
529 	 * 
530 	 * @return
531 	 */
532 	public boolean isScaleIcons() {
533 		return scaleIcons;
534 	}
535 	
536 	public static void main(String[] args) {
537 
538 		final IconDisplayer id = new IconDisplayer();
539 		id.setPopupEnabled(false);
540 		ValueIconPair[] icons = new ValueIconPair[]{
541 		new ValueIconPair(0L, IconHelper.createIcon("icons/navigation/ArrowLeftLeft16.gif")),
542 		        new ValueIconPair(1L, IconHelper.createIcon("icons/navigation/ArrowLeft16.gif")),
543 		        new ValueIconPair(2L, IconHelper.createIcon("icons/navigation/ArrowRight16.gif")),
544 		        new ValueIconPair(3L, IconHelper.createIcon("icons/navigation/ArrowRightRight16.gif"))
545 		};
546 		id.setIcons(icons);
547 		
548 		Thread th = new Thread(new Runnable(){
549 			public void run() {
550 				try {
551 					int i = 0;
552 
553 					while (true) {
554 						id.setValue(i);
555 						i = (i + 1) % 5;
556 						Thread.sleep(5000);
557 					}
558 				} catch (InterruptedException e) {
559 				}				
560 			}
561 		});
562 		id.setTitle("Demo");
563 		RunnerHelper.runComponent(id, 300,300);
564 		th.start();
565 	}
566 }
567 
568 /* __oOo__ */