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.selector;
24  
25  import java.awt.Dimension;
26  import java.awt.GridBagConstraints;
27  import java.awt.GridBagLayout;
28  import java.awt.Insets;
29  import java.awt.event.ActionEvent;
30  import java.awt.event.ActionListener;
31  import java.awt.event.KeyAdapter;
32  import java.awt.event.KeyEvent;
33  import java.beans.Beans;
34  import java.beans.Customizer;
35  import java.beans.PropertyChangeEvent;
36  import java.beans.PropertyChangeListener;
37  import java.beans.PropertyVetoException;
38  import java.util.ArrayList;
39  import java.util.Vector;
40  import java.util.concurrent.ExecutorService;
41  import java.util.concurrent.Executors;
42  
43  import javax.swing.DefaultListCellRenderer;
44  import javax.swing.DefaultListModel;
45  import javax.swing.JButton;
46  import javax.swing.JLabel;
47  import javax.swing.JList;
48  import javax.swing.JPanel;
49  import javax.swing.JScrollPane;
50  import javax.swing.JTabbedPane;
51  import javax.swing.ListCellRenderer;
52  import javax.swing.event.ListSelectionEvent;
53  import javax.swing.event.ListSelectionListener;
54  
55  import com.cosylab.gui.adapters.Converter;
56  import com.cosylab.gui.adapters.ConverterCustomizer;
57  import com.cosylab.gui.components.util.IconHelper;
58  import com.cosylab.util.CommonException;
59  
60  import de.desy.acop.displayers.tools.AcopDisplayer;
61  import de.desy.acop.displayers.tools.AcopDisplayerParameters;
62  import de.desy.acop.displayers.tools.MultipleAcopDisplayer;
63  import de.desy.acop.transport.ConnectionParameters;
64  
65  /**
66   * <code>MultipleConnectionCustomizer</code> is customizer panel
67   * that enables selection of multiple <code>AcopDisplayerParameters</code>.
68   * This component is intended to be used with <code>MultipleAcopDisplayer</code>s.
69   * <p>
70   * The component constis of the parameters selector and customization user
71   * interface where the displayer parameters cen be constructed and then added
72   * to the displayer. The left side of the panel shows the list of all 
73   * displayer parameters on the displayer that this customizer belongs to.
74   * </p>  
75   * 
76   * @author <a href="mailto:jaka.bobnar@cosylab.com">Jaka Bobnar</a>
77   * @version $Id: Templates.xml,v 1.10 2004/01/13 16:17:13 jbobnar Exp $
78   *
79   * @param <T> AcopDisplayerParameters that are being handled by this class
80   * @see MultipleAcopDisplayer
81   */
82  public abstract class MultipleConnectionCustomizer<T extends AcopDisplayerParameters> extends JPanel implements Customizer {
83  
84  
85  	private static final long serialVersionUID = 4596748128425127898L;
86  	
87  	private MultipleAcopDisplayer<T> disp;
88  	
89  	private SelectorGUI selectorGUI;
90  	private JPanel selectorPanel;
91  	private JList selectionList;
92  	private DefaultListModel listModel;
93  	private JScrollPane selectionScroll;
94  	private JLabel selectedLabel;
95  	private JButton removeButton;
96  	private JTabbedPane tabPane;
97  	private ConverterCustomizer converterCustomizer;
98  	
99  	private JButton addButton;
100 	private JButton applyButton;
101 	private JPanel converterP;
102 	
103 	protected T selectedParameters;
104 		
105 	protected Vector<T> displayerParameters = new Vector<T>();
106 	
107 	private ExecutorService executor = Executors.newSingleThreadExecutor();
108 
109 	/**
110 	 * Constructs a new MultipleConnectionCustomizer.
111 	 *
112 	 */
113 	public MultipleConnectionCustomizer() {
114 		super();
115 		initialize();
116 		
117 	}
118 	
119 	private void initialize() {
120 		this.setLayout(new GridBagLayout());
121 		this.add(getSelectorPanel(), new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(11,11,11,11),0,0));
122 		
123 	}
124 	
125 	private JPanel getSelectorPanel() {
126 		if (selectorPanel == null) {
127 			selectorPanel = new JPanel(new GridBagLayout());
128 			selectedLabel = new JLabel("Selected connections: ");
129 			selectedLabel.setPreferredSize(new Dimension(200,21));
130 			selectedLabel.setMinimumSize(new Dimension(200,21));
131 			selectedLabel.setMaximumSize(new Dimension(200,21));
132 			selectorPanel.add(selectedLabel, new GridBagConstraints(0,0,1,1,1,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0));		
133 			selectorPanel.add(getSelectionScroll(), new GridBagConstraints(0,1,1,1,1,1,GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0,0,0,0), 0,0));
134 			selectorPanel.add(getRemoveButton(), new GridBagConstraints(0,2,1,1,1,0,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10,0,0,0), 0,0));
135 			selectorPanel.add(getCustomizerTabbedPane(), new GridBagConstraints(1,0,1,2,0,1,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,11,0,0),0,0));
136 			if (Beans.isDesignTime()) {
137 				JPanel p = new JPanel(new GridBagLayout());
138 				p.add(getAddButton(), new GridBagConstraints(0,0,1,1,0,0,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0,0,0,5),0,0));
139 				p.add(getApplyButton() , new GridBagConstraints(1,0,1,1,0,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(00,5,0,0),0,0));
140 				selectorPanel.add(p, new GridBagConstraints(1,2,1,1,0,0,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10,11,0,0),0,0));
141 			} else {
142 				selectorPanel.add(getAddButton(), new GridBagConstraints(1,2,1,1,0,0,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10,0,0,0),0,0));
143 			}
144 		
145 		}
146 		return selectorPanel;
147 	}
148 	
149 	private JButton getApplyButton() {
150 		if (applyButton == null) {
151 			applyButton = new JButton("Apply");
152 			applyButton.setEnabled(false);
153 			applyButton.addActionListener(new ActionListener() {
154 				public void actionPerformed(ActionEvent e) {
155 					if (selectedParameters != null) {
156 						if (disp != null) {
157 		        			disp.removeDisplayerParameters(selectedParameters);
158 		        		} else {
159 	        				removeDisplayerParameters(selectedParameters);
160 		        		}
161 						T param = generateAndAddDisplayerParameters();
162 						getSelectionList().setSelectedValue(param, true);
163 		    		    getSettingsPanel().setParameters(param);
164 					}
165 				}
166 			});
167 		}
168 		return applyButton;
169 	}
170 	
171 	private JButton getRemoveButton() {
172 		if (removeButton == null) {
173 	        removeButton = new JButton("Remove", IconHelper.createIcon("icons/navigation/Minus16.gif"));
174 	        removeButton.addActionListener(new ActionListener() {
175 	        	@SuppressWarnings("unchecked")
176 				public void actionPerformed(ActionEvent e) {
177 	        		Object[] selected = getSelectionList().getSelectedValues();
178 	        		if (disp != null) {
179 	        			for (Object p: selected) {
180 	        				disp.removeDisplayerParameters((T)p);
181 	        			}
182 	        		} else {
183 	        			for (Object p: selected) {
184 	        				removeDisplayerParameters((T)p);
185 	        			}
186 	        		}
187 	        	
188 	        	}
189 	        });
190 	        removeButton.setEnabled(false);
191 	        
192         }
193 
194         return removeButton;
195 	}
196 	
197 	protected JButton getAddButton() {
198 		if (addButton == null) {
199 			addButton = new JButton("Add", IconHelper.createIcon("icons/navigation/Plus16.gif"));
200 			addButton.addActionListener(new ActionListener() {
201 	        	public void actionPerformed(ActionEvent e) {
202 	        		executor.execute(new Runnable(){
203 	        			@Override
204 	        			public void run() {
205 	        				T param = generateAndAddDisplayerParameters();
206 	    	        		getSettingsPanel().setParameters(param);	        				
207 	        			}
208 	        		});
209 	        	}
210 	        });
211 			addButton.setEnabled(false);
212 	        
213         }
214 
215         return addButton;
216 	}
217 	
218 	private JScrollPane getSelectionScroll() {
219 		if (selectionScroll == null) {
220 	        selectionScroll = new JScrollPane(getSelectionList());
221         }
222         return selectionScroll;
223     }
224 	
225 	protected ListCellRenderer getListRenderer() {
226 		return new DefaultListCellRenderer();
227 	}
228 	
229 	protected JList getSelectionList() {
230 		if (selectionList == null) {
231 	        selectionList = new JList();
232 	        selectionList.setPreferredSize(new Dimension(200,200));
233 	        selectionList.setModel(getModel());
234 	        selectionList.setCellRenderer(getListRenderer());
235 	        selectionList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
236 	        	@SuppressWarnings("unchecked")
237 				public void valueChanged(ListSelectionEvent e) {
238 	        		if (getSelectionList().getSelectedIndex() >= 0) {
239 	        			getRemoveButton().setEnabled(true);
240 	        		} else {
241 	        			getRemoveButton().setEnabled(false);
242 	        		}
243 	        		
244 	        		int sel = selectionList.getSelectedIndex();
245 	        		if (sel >= 0) {
246 	        			T parameters = (T) getModel().getElementAt(sel);
247 	        			setSelectedParameters(parameters);
248 	        			getSelectorGUI().setConnectionParameters(parameters.getConnectionParameters());
249 	        			getSettingsPanel().setParameters(parameters);
250 	        		} else {
251 	        			setSelectedParameters(null);
252 	        		}
253 	        	}
254 	        });
255 	        selectionList.addKeyListener(new KeyAdapter() {
256 	        	@SuppressWarnings("unchecked")
257 				@Override
258 	        	public void keyPressed(KeyEvent e) {
259 	        		if (e.getKeyCode() == KeyEvent.VK_DELETE) {
260 	        			Object[] selected = selectionList.getSelectedValues();
261 	        			if (disp != null) {
262 		        			for (Object p: selected) {
263 		        				disp.removeDisplayerParameters((T)p);
264 		        			}
265 		        		} else {
266 		        			for (Object p: selected) {
267 		        				removeDisplayerParameters((T)p);
268 		        			}
269 		        		}
270 	        		}
271 	        	}
272 	        });
273         }
274 		return selectionList;
275     }
276 	
277 	private DefaultListModel getModel() {
278 		if (listModel == null) {
279 	        listModel = new DefaultListModel();
280         }
281 
282         return listModel;
283 	}
284 	
285 
286 	protected JTabbedPane getCustomizerTabbedPane() {
287 		if (tabPane == null) {
288 			tabPane = new JTabbedPane();
289 			JPanel selectorP = new JPanel(new GridBagLayout());
290 			selectorP.add(getSelectorGUI(), new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(11,11,11,11),0,0));
291 			JPanel customizerP = new JPanel(new GridBagLayout());
292 			customizerP.add(getSettingsPanel(), new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(11,11,11,11),0,0));
293 			converterP = new JPanel(new GridBagLayout());
294 			converterP.add(getConverterPanel(), new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(11,11,11,11),0,0));
295 			tabPane.addTab("Connection", selectorP);
296 			tabPane.addTab("Style", customizerP);
297 			tabPane.addTab("Converter", converterP);
298 		}
299 		
300 		return tabPane;
301 	}
302 	
303 	protected ConverterCustomizer getConverterPanel() {
304 		if (converterCustomizer == null) {
305 			converterCustomizer = new ConverterCustomizer();
306 			converterCustomizer.setPreferredSize(new Dimension(200,200));
307 		}
308 
309 		return converterCustomizer;
310 	}
311 
312 	protected abstract MultipleDisplayerAbstractSettingsPanel<T> getSettingsPanel();
313 		
314 	protected SelectorGUI getSelectorGUI() {
315 		if (selectorGUI == null) {
316 			selectorGUI = new SelectorGUI();
317 			selectorGUI.addSelectorGUIListener(new SelectorGUIListener() {
318 				public void selectionChanged(SelectorGUIEvent e) {
319 					getAddButton().setEnabled(SelectorUtilities.isConnectionParametersValid(selectorGUI.getConnectionParameters()));
320 				}
321 			});
322 			selectorGUI.addPropertyChangeListener(AcopDisplayer.CONNECTION_PARAMETERS_PROPERTY,new PropertyChangeListener() {
323 				public void propertyChange(PropertyChangeEvent e) {
324 					getAddButton().setEnabled(SelectorUtilities.isConnectionParametersValid(selectorGUI.getConnectionParameters()));
325 				}
326 			});
327 	    }
328 	    return selectorGUI;
329     }
330 	
331 	protected abstract T generateParameters();
332 	
333 	private T generateAndAddDisplayerParameters() {
334 		T param = generateParameters();
335 		addDisplayerParameters(param);
336 		return param;
337 	}
338 	
339 	private void addDisplayerParameters(T agp) {
340 		if (agp == null || displayerParameters.contains(agp)) return;
341 		T[] old = getDisplayerParameters();
342 		getModel().addElement(agp);
343 		displayerParameters.add(agp);
344 				
345 	    if (disp != null) {
346 		    try {
347                 disp.addDisplayerParameters(agp);
348             } catch (CommonException e1) {
349             	getSelectorGUI().handleException(e1);
350             } catch (PropertyVetoException e1) {
351             	getSelectorGUI().handleException(e1);
352             }
353 	    }
354 		
355 		firePropertyChange(MultipleAcopDisplayer.DISPLAYER_PARAMETERS_PROPERTY,old,getDisplayerParameters());
356 	}
357 	
358 	private void removeDisplayerParameters(T agp) {
359 		if (agp == null || !displayerParameters.contains(agp)) return;
360 		T[] old = getDisplayerParameters();
361 		getModel().removeElement(agp);
362 		displayerParameters.remove(agp);
363 		
364 		firePropertyChange(MultipleAcopDisplayer.DISPLAYER_PARAMETERS_PROPERTY,old,getDisplayerParameters());
365 	}
366 
367 	/*
368 	 * (non-Javadoc)
369 	 * @see java.beans.Customizer#setObject(java.lang.Object)
370 	 */
371 	@SuppressWarnings("unchecked")
372 	public void setObject(Object bean) {
373 		disp = (MultipleAcopDisplayer<T>)bean;
374 		getSelectorGUI().setObject(bean);
375 		setDisplayerParameters(disp.getDisplayerParameters());
376 		disp.addPropertyChangeListener(MultipleAcopDisplayer.DISPLAYER_PARAMETERS_PROPERTY, new PropertyChangeListener(){
377 
378 			public void propertyChange(PropertyChangeEvent evt) {
379 				if (!MultipleAcopDisplayer.DISPLAYER_PARAMETERS_PROPERTY.equals(evt.getPropertyName())) 
380 					return;
381 				setDisplayerParameters(disp.getDisplayerParameters());
382 			}
383 		});     
384     }
385 
386 	/**
387 	 * Returns an array of displayer parameters containing all displayer parameters.
388 	 * (use displayerParameters vector and cast elements to T)
389      * @return displayerParameters
390      */
391     public abstract T[] getDisplayerParameters();
392 
393 	/**
394 	 * Sets displayer parameters to this customizer. This parameters will be displayed
395 	 * as parameters set on the displayer and will be listed in the left list.
396 	 * 
397      * @param cps selected parameters
398      */
399     public void setDisplayerParameters(T[] parameters) {
400     	if (parameters == null) return;
401 		T[] old = getDisplayerParameters();
402 		ArrayList<T> toBeRemoved = new ArrayList<T>();
403 		
404 		if (displayerParameters != null) {
405 			for(T cp : displayerParameters) {
406 				toBeRemoved.add(cp);
407 			}
408 		}
409 		
410 		ArrayList<T> toBeAdded = new ArrayList<T>();
411 	
412 		for (T p : parameters) {
413 			if (toBeRemoved.contains(p)) {
414 				toBeRemoved.remove(p);
415 			} else {
416 				toBeAdded.add(p);
417 			}
418 		}
419 		
420 		for (T p : toBeRemoved) {
421 			getModel().removeElement(p);
422 			displayerParameters.remove(p);
423 		}
424 		
425 		for (T p : toBeAdded) {
426 			if (!displayerParameters.contains(p)) {
427 				getModel().addElement(p);
428 				displayerParameters.add(p);
429 			}
430 		}
431 		
432 		firePropertyChange(MultipleAcopDisplayer.DISPLAYER_PARAMETERS_PROPERTY,old,getDisplayerParameters());
433 		
434     }
435     
436     protected void setSelectedParameters(T selected) {
437     	this.selectedParameters = selected;
438     	if (this.selectedParameters != null || SelectorUtilities.isConnectionParametersValid(getSelectorGUI().getConnectionParameters())) {
439     		getApplyButton().setEnabled(true);
440     		getAddButton().setEnabled(true);
441     		if (selectedParameters != null && selectedParameters.getConverter()!=null) {
442     			Converter c = selectedParameters.getConverter();
443 				try {
444 					c= (Converter)c.clone();
445 				} catch (CloneNotSupportedException e) {
446 					e.printStackTrace();
447 				}
448     			getConverterPanel().setConverter(c);
449     		} else {
450     			getConverterPanel().setConverter(null);
451     		}
452     	} else {
453     		getApplyButton().setEnabled(false);
454     		getAddButton().setEnabled(false);
455     		getConverterPanel().setConverter(null);
456     	} 		
457     }
458     
459     /**
460      * Enables/disables the converter customizer tab.
461      * 
462      * @param enabled true if converter tab should be enabled
463      */
464     public void setConverterTabEnabled(boolean enabled){
465     	for (int i = 0; i < tabPane.getComponentCount(); i++) if (tabPane != null && tabPane.getComponentAt(i).equals(converterP)){
466     		tabPane.setEnabledAt(i, enabled);
467     		break;
468     	}
469     }
470     
471     /**
472      * This method will select the given ConnectionParameters in the combo box browsers.
473      * 
474      * @param p
475      */
476     public void applyConnectionParameters(ConnectionParameters p) {
477     	getSelectorGUI().setConnectionParameters(p);
478     }
479     
480     protected MultipleAcopDisplayer<T> getDisplayer() {
481     	return disp;
482     }
483     
484 }
485 
486 
487 /* __oOo__ */