View Javadoc

1   /*
2    * @(#)$Id: TestClassPanel.java 798 2010-05-04 15:04:37Z bpuype $
3    *
4    * Author		:	Ueli Kurmann, igesture@uelikurmann.ch
5    *                  
6    *
7    * Purpose		: 
8    *
9    * -----------------------------------------------------------------------
10   *
11   * Revision Information:
12   *
13   * Date				Who			Reason
14   *
15   * 07.10.2008			ukurmann	Initial Release
16   *
17   * -----------------------------------------------------------------------
18   *
19   * Copyright 1999-2009 ETH Zurich. All Rights Reserved.
20   *
21   * This software is the proprietary information of ETH Zurich.
22   * Use is subject to license terms.
23   * 
24   */
25  
26  package org.ximtec.igesture.tool.view.testset.panel;
27  
28  import java.awt.BorderLayout;
29  import java.awt.CardLayout;
30  import java.awt.Color;
31  import java.awt.Dimension;
32  import java.awt.FlowLayout;
33  import java.awt.GridBagLayout;
34  import java.awt.event.ComponentAdapter;
35  import java.awt.event.ComponentEvent;
36  import java.util.HashMap;
37  import java.util.List;
38  import java.util.Map;
39  
40  import javax.swing.BorderFactory;
41  import javax.swing.JButton;
42  import javax.swing.JLabel;
43  import javax.swing.JPanel;
44  import javax.swing.JTextField;
45  
46  import org.sigtec.graphix.GridBagLayouter;
47  import org.ximtec.igesture.core.Gesture;
48  import org.ximtec.igesture.core.TestClass;
49  import org.ximtec.igesture.io.AbstractGestureDevice;
50  import org.ximtec.igesture.io.DeviceManagerListener;
51  import org.ximtec.igesture.io.GestureDevice;
52  import org.ximtec.igesture.io.GestureDevicePanel;
53  import org.ximtec.igesture.io.IDeviceManager;
54  import org.ximtec.igesture.tool.GestureConstants;
55  import org.ximtec.igesture.tool.binding.BindingFactory;
56  import org.ximtec.igesture.tool.core.Controller;
57  import org.ximtec.igesture.tool.gesturevisualisation.GesturePanel;
58  import org.ximtec.igesture.tool.gesturevisualisation.InputComponentPanel;
59  import org.ximtec.igesture.tool.gesturevisualisation.InputPanelFactory;
60  import org.ximtec.igesture.tool.service.DeviceManagerService;
61  import org.ximtec.igesture.tool.service.SwingMouseReaderService;
62  import org.ximtec.igesture.tool.util.Formatter;
63  import org.ximtec.igesture.tool.util.TitleFactory;
64  import org.ximtec.igesture.tool.view.AbstractPanel;
65  import org.ximtec.igesture.tool.view.DeviceListPanel;
66  import org.ximtec.igesture.tool.view.DeviceListPanelListener;
67  import org.ximtec.igesture.tool.view.admin.action.ClearGestureSampleAction;
68  import org.ximtec.igesture.tool.view.admin.panel.SampleDescriptorPanel;
69  import org.ximtec.igesture.tool.view.testset.action.AddSampleAction;
70  import org.ximtec.igesture.tool.view.testset.action.RemoveSampleAction;
71  
72  /**
73   * Comment
74   * 
75   * @version 1.0 07.10.2008
76   * @author Ueli Kurmann
77   */
78  
79  public class TestClassPanel extends AbstractPanel implements DeviceListPanelListener, DeviceManagerListener {
80  
81    private static final int INPUTAREA_SIZE = 200;
82    private static final int SPACE_SIZE = 5;
83    private static final int SAMPLE_SIZE = 100;
84  
85    private GestureDevice<?, ?> gestureDevice;
86    private GestureDevice<?, ?> currentDevice;
87  
88    private Map<Gesture<?>, JPanel> sampleCache;
89    private TestClass testClass;
90    
91    private DeviceListPanel devicePanel;
92    private JPanel cardPanel; 
93    
94    private Map<String, InputComponentPanel> panelMapping;
95  
96    /**
97     * Constructor
98     * 
99     * @param controller
100    * @param descriptor
101    */
102   public TestClassPanel(Controller controller, TestClass testClass) {
103     super(controller);
104     this.testClass = testClass;
105     this.sampleCache = new HashMap<Gesture<?>, JPanel>();
106     this.panelMapping = new HashMap<String, InputComponentPanel>();
107 
108     // component listener to handle resize actions
109     addComponentListener(new ComponentAdapter() {
110       @Override
111       public void componentResized(ComponentEvent e) {
112         initSampleSection(TestClassPanel.this.testClass.getGestures());
113       }
114     });
115     
116     DeviceManagerService manager = controller.getLocator().getService(DeviceManagerService.IDENTIFIER, DeviceManagerService.class);
117     manager.addDeviceManagerListener(this);
118 
119     init(manager);
120 
121   }
122 
123   private JButton createAddSampleButton(GestureDevice<?, ?> device) {
124     JButton addSampleButton = getComponentFactory().createButton(GestureConstants.GESTURE_SAMPLE_ADD,
125         new AddSampleAction(getController(), testClass, device));
126     Formatter.formatButton(addSampleButton);
127     return addSampleButton;
128   }
129 
130   private JButton createClearSampleButton(GestureDevice<?, ?> gestureDevice) {
131     JButton clearSampleButton = getComponentFactory().createButton(GestureConstants.GESTURE_SAMPLE_CLEAR,
132         new ClearGestureSampleAction(getController(), gestureDevice));
133     Formatter.formatButton(clearSampleButton);
134     return clearSampleButton;
135   }
136 
137   /**
138    * Returns the visualization of a gesture. A hash map is used to cache these
139    * visualizations. Otherwise every update of the view requires the computation
140    * of all samples.
141    * 
142    * The cache is very simple and it's elements are never removed. This simple
143    * implementation is sufficient, because of the short life-cycle of the
144    * explorer tree views.
145    * 
146    * @param sample
147    * @return
148    */
149   private synchronized JPanel createSampleIcon(final Gesture<?> sample) {
150 
151     if (sampleCache.containsKey(sample)) {
152       return sampleCache.get(sample);
153     }
154 
155     GesturePanel gesturePanel = InputPanelFactory.createGesturePanel(sample);
156     final JPanel panel = gesturePanel.getPanel(new Dimension(SAMPLE_SIZE, SAMPLE_SIZE));
157     panel.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1));
158     RemoveSampleAction action = new RemoveSampleAction(getController(), TestClassPanel.this.testClass, sample);
159 
160     panel.addMouseListener(new SampleDescriptorPanel.SampleIconMouseListener(action, panel));
161     panel.setOpaque(true);
162     panel.setBackground(Color.WHITE);
163     sampleCache.put(sample, panel);
164 
165     return panel;
166 
167   }
168 
169   /**
170    * Returns a white, square spacer element (JPanel) of the given size.
171    * 
172    * @param size
173    *          the size of the space element
174    * @return the space element
175    */
176   private JPanel createSpacerPanel(int size) {
177     JPanel panel = new JPanel();
178     panel.setLayout(null);
179     panel.setOpaque(true);
180     panel.setBackground(Color.WHITE);
181     panel.setPreferredSize(new Dimension(size, size));
182     return panel;
183   }
184 
185   /**
186    * Initialize the Sample Descriptor View
187  * @param manager 
188    * 
189    * @param descriptor
190    */
191   private void init(IDeviceManager manager) {
192     initTitle();
193     initSampleSection(testClass.getGestures());
194     initInputSection(manager);
195   }
196 
197   /**
198    * Captures a local reference of the gesture input device.
199    */
200   private void initGestureDevice() {
201     gestureDevice = getController().getLocator().getService(SwingMouseReaderService.IDENTIFIER, GestureDevice.class);
202   }
203 
204   /**
205    * Creates the input area to capture new gestures.
206  * @param manager 
207    * 
208    * @param descriptor
209    */
210   private void initInputSection(IDeviceManager manager) {
211 	  JPanel basePanel = new JPanel();
212 	    
213 	    // input area
214 	    basePanel.setLayout(new BorderLayout());
215 
216 	    initGestureDevice();
217 	    
218 		cardPanel = new JPanel();
219 		cardPanel.setLayout(new CardLayout());
220 		cardPanel.setSize(new Dimension(INPUTAREA_SIZE, INPUTAREA_SIZE));
221 		
222 		currentDevice = gestureDevice;
223 		
224 	    basePanel.add(cardPanel, BorderLayout.CENTER);
225 	    
226 	    devicePanel = new DeviceListPanel();
227 	    for(AbstractGestureDevice<?,?> device : manager.getDevices())
228 	    	addDevice(device);
229 	    devicePanel.addDevicePanelListener(this);
230 	    basePanel.add(devicePanel,BorderLayout.WEST);
231 	    
232 	    setBottom(basePanel);	  
233   }
234 
235   /**
236    * Visualizes the samples. The GridBagLayout is used. The number of elements
237    * in a row are computed dynamically. Between two gesture elements a space
238    * element is placed.
239    */
240   private synchronized void initSampleSection(List<Gesture<?>> samples) {
241 
242     JPanel title = new JPanel();
243     title.setLayout(new FlowLayout(FlowLayout.LEFT));
244     JLabel label = getComponentFactory().createLabel(GestureConstants.TESTCLASS_NAME);
245     title.add(label);
246     JTextField textField = new JTextField();
247     Formatter.formatTextField(textField);
248     title.add(textField);
249     BindingFactory.createInstance(textField, testClass, TestClass.PROPERTY_NAME);
250 
251     title.setOpaque(true);
252     title.setBackground(Color.WHITE);
253     
254     JPanel samplePanel = new JPanel();
255 
256     samplePanel.setLayout(new GridBagLayout());
257 
258     // if the component has size 0 (before it is placed into another container
259     // component, don't visualize the samples
260     if (getWidth() > 0) {
261 
262       int x = 0;
263       int y = 1;
264 
265       // compute the number of samples shown in a row
266       int elementsPerRow = (getWidth() - 20) / (SAMPLE_SIZE + 20);
267       elementsPerRow = elementsPerRow * 2 - 1;
268 
269       // add a line of space elements before the first row
270       GridBagLayouter.addComponent(samplePanel, createSpacerPanel(SPACE_SIZE), 0, 0);
271 
272       // iterate over all the samples
273       for (final Gesture<?> sample : samples) {
274         GridBagLayouter.addComponent(samplePanel, createSampleIcon(sample), x, y);
275         GridBagLayouter.addComponent(samplePanel, createSpacerPanel(SPACE_SIZE), x + 1, y);
276         if (x + 1 >= elementsPerRow) {
277           x = 0;
278           y++;
279           // add a line (spacer) between two sample rows
280           GridBagLayouter.addComponent(samplePanel, createSpacerPanel(SPACE_SIZE), 0, y);
281           y++;
282         } else {
283           // element + spacer = 2
284           x = x + 2;
285         }
286 
287       }
288     }
289 
290     samplePanel.setOpaque(true);
291     samplePanel.setBackground(Color.WHITE);
292     samplePanel.setAutoscrolls(true);
293 
294     JPanel contentPanel = new JPanel();
295     contentPanel.setLayout(new BorderLayout());
296     contentPanel.setOpaque(true);
297     contentPanel.setBackground(Color.WHITE);
298 
299     contentPanel.add(title, BorderLayout.NORTH);
300    
301     contentPanel.add(samplePanel, BorderLayout.CENTER);
302 
303     setContent(contentPanel);
304   }
305 
306   /**
307    * Sets the title of the form
308    */
309   private void initTitle() {
310 
311     StringBuilder sb = new StringBuilder();
312     sb.append(testClass.getName());
313 
314     JLabel titleLabel = TitleFactory.createStaticTitle(sb.toString());
315     BindingFactory.createInstance(titleLabel, testClass, TestClass.PROPERTY_NAME);
316     setTitle(titleLabel);
317   }
318 
319   @Override
320   public void refreshUILogic() {
321     super.refreshUILogic();
322     gestureDevice.clear();
323     initSampleSection(testClass.getGestures());
324   }
325 
326 	/* (non-Javadoc)
327 	 * @see org.ximtec.igesture.tool.view.DeviceListPanelListener#updateDeviceListPanelListener(org.ximtec.igesture.io.AbstractGestureDevice)
328 	 */
329 	@Override
330 	public void updateDeviceListPanelListener(AbstractGestureDevice<?, ?> device) {
331 		
332 		//remove listener from current device
333 		if(currentDevice != null)
334 			currentDevice.removeGestureHandler(panelMapping.get(currentDevice.toString()).getGestureDevicePanel());
335 		//change input panel
336 		((CardLayout)cardPanel.getLayout()).show(cardPanel, device.toString());
337 		currentDevice = device;
338 		
339 		//add listener to new device
340 		device.addGestureHandler(panelMapping.get(device.toString()).getGestureDevicePanel());
341 		
342 		repaint();
343 	}
344 	
345 	private InputComponentPanel createInputPanel(GestureDevice<?,?> device)
346 	{
347 		InputComponentPanel inputComponentPanel = new InputComponentPanel();
348 		inputComponentPanel.setLayout(new FlowLayout());
349 		GestureDevicePanel inputPanelInstance = InputPanelFactory.createPanel(device);
350 		inputComponentPanel.setGestureDevicePanel(inputPanelInstance);
351 		inputComponentPanel.add(inputPanelInstance);
352 		
353 		// buttons
354 	    JPanel buttonPanel = new JPanel();
355 	    buttonPanel.setLayout(new BorderLayout());
356 	    buttonPanel.add(createAddSampleButton(device),BorderLayout.NORTH);
357 	    buttonPanel.add(createClearSampleButton(device),BorderLayout.CENTER);
358 	    
359 	    inputComponentPanel.add(buttonPanel);	 
360 		
361 		return inputComponentPanel;
362 	}
363 	
364 	private void addDevice(AbstractGestureDevice<?,?> device)
365 	{
366 //		if(device.getDeviceType() == "2D")
367 		{
368 			//add input panel
369 			InputComponentPanel panel = createInputPanel(device);
370 			panelMapping.put(device.toString(), panel);
371 			cardPanel.add(panel,device.toString());
372 			//add device to device list
373 			devicePanel.addDevice(device);
374 		}
375 	}
376 	
377 	private void removeDevice(AbstractGestureDevice<?,?> device)
378 	{
379 //		if(device.getDeviceType() == "2D")
380 		{
381 			devicePanel.removeDevice(device);
382 			//remove input panel
383 			InputComponentPanel panel = panelMapping.get(device.toString());
384 			cardPanel.remove(panel);
385 		}
386 	}
387 	
388 	/* (non-Javadoc)
389 	 * @see org.ximtec.igesture.tool.view.devicemanager.DeviceManagerListener#updateDeviceManagerListener(int, org.ximtec.igesture.io.AbstractGestureDevice)
390 	 */
391 	@Override
392 	public void updateDeviceManagerListener(int operation, AbstractGestureDevice<?, ?> device) {
393 		if(operation == DeviceManagerListener.ADD)
394 		{
395 			addDevice(device);
396 		} 
397 		else if(operation == DeviceManagerListener.REMOVE)
398 		{
399 			removeDevice(device);
400 		}
401 	}
402 
403 }