1   package junit.swingui;
2   
3   import java.awt.*;
4   import java.awt.event.*;
5   import java.util.*;
6   
7   import javax.swing.*;
8   import javax.swing.event.*;
9   import junit.runner.*;
10  
11  /***
12   * A test class selector. A simple dialog to pick the name of a test suite.
13   */
14  class TestSelector extends JDialog {
15  	private JButton fCancel;
16  	private JButton fOk;
17  	private JList fList;
18  	private JScrollPane fScrolledList;
19  	private JLabel fDescription;
20  	private String fSelectedItem;
21  	
22  	/***
23  	 * Renders TestFailures in a JList
24  	 */
25  	static class TestCellRenderer extends DefaultListCellRenderer {
26  		Icon fLeafIcon;
27  		Icon fSuiteIcon;
28  		
29  		public TestCellRenderer() {
30  			fLeafIcon= UIManager.getIcon("Tree.leafIcon");
31  			fSuiteIcon= UIManager.getIcon("Tree.closedIcon");
32  		}
33  		
34  		public Component getListCellRendererComponent(
35  				JList list, Object value, int modelIndex, 
36  				boolean isSelected, boolean cellHasFocus) {
37  			Component c= super.getListCellRendererComponent(list, value, modelIndex, isSelected, cellHasFocus);
38  			String displayString= displayString((String)value);
39  			
40  			if (displayString.startsWith("AllTests"))
41  				setIcon(fSuiteIcon);
42  			else
43  				setIcon(fLeafIcon);
44  				
45  			setText(displayString);
46  		    	return c;
47  		}
48  		
49  		public static String displayString(String className) {
50  			int typeIndex= className.lastIndexOf('.');
51      			if (typeIndex < 0) 
52      				return className;
53      			return className.substring(typeIndex+1) + " - " + className.substring(0, typeIndex);
54  		}
55  		
56  		public static boolean matchesKey(String s, char ch) {
57      			return ch == Character.toUpperCase(s.charAt(typeIndex(s)));
58  		}
59  		
60  		private static int typeIndex(String s) {
61  			int typeIndex= s.lastIndexOf('.');
62  			int i= 0;
63      			if (typeIndex > 0) 
64      				i= typeIndex+1;
65      			return i;
66  		}
67  	}
68  	
69  	protected class DoubleClickListener extends MouseAdapter {
70  		public void mouseClicked(MouseEvent e) {
71  	    		if (e.getClickCount() == 2) {
72  	    			okSelected();
73  	    		}
74  	      }
75  	}
76  	
77  	protected class KeySelectListener extends KeyAdapter {
78  		public void keyTyped(KeyEvent e) {
79  			keySelectTestClass(e.getKeyChar());
80  		}
81  	}
82  
83  	public TestSelector(Frame parent, TestCollector testCollector) {
84  		super(parent, true);
85  		setSize(350, 300);
86  		setResizable(false);
87  		// setLocationRelativeTo only exists in 1.4
88  		try {
89  			setLocationRelativeTo(parent);
90  		} catch (NoSuchMethodError e) {
91  			centerWindow(this);
92  		}
93  		setTitle("Test Selector");
94  		
95  		Vector list= null;
96  		try {
97  			parent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
98  			list= createTestList(testCollector);
99  		} finally {
100 			parent.setCursor(Cursor.getDefaultCursor());
101 		}
102 		fList= new JList(list);
103 		fList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
104 		fList.setCellRenderer(new TestCellRenderer());
105 		fScrolledList= new JScrollPane(fList);
106 
107 		fCancel= new JButton("Cancel");
108 		fDescription= new JLabel("Select the Test class:");
109 		fOk= new JButton("OK");
110 		fOk.setEnabled(false);
111 		getRootPane().setDefaultButton(fOk);
112 		
113 		defineLayout();
114 		addListeners();
115 	}
116 
117 	public static void centerWindow(Component c) {
118 		Dimension paneSize= c.getSize();
119 		Dimension screenSize= c.getToolkit().getScreenSize();
120 		c.setLocation((screenSize.width-paneSize.width)/2, (screenSize.height-paneSize.height)/2);
121 	}
122 	
123 	private void addListeners() {
124 		fCancel.addActionListener(
125 			new ActionListener() {
126 				public void actionPerformed(ActionEvent e) {
127 					dispose();
128 				}
129 			}
130 		);
131 		
132 		fOk.addActionListener(
133 			new ActionListener() {
134 				public void actionPerformed(ActionEvent e) {
135 					okSelected();
136 				}
137 			}
138 		);
139 
140 		fList.addMouseListener(new DoubleClickListener());
141 		fList.addKeyListener(new KeySelectListener());
142 		fList.addListSelectionListener(
143 			new ListSelectionListener() {
144 				public void valueChanged(ListSelectionEvent e) {
145 					checkEnableOK(e);
146 				}
147 			}
148 		);
149 
150 		addWindowListener(
151 			new WindowAdapter() {
152 				public void windowClosing(WindowEvent e) {
153 					dispose();
154 				}
155 			}
156 		);
157 	}
158 	
159 	private void defineLayout() {
160 		getContentPane().setLayout(new GridBagLayout());
161 		GridBagConstraints labelConstraints = new GridBagConstraints();
162 		labelConstraints.gridx= 0; labelConstraints.gridy= 0;
163 		labelConstraints.gridwidth= 1; labelConstraints.gridheight= 1;
164 		labelConstraints.fill= GridBagConstraints.BOTH;
165 		labelConstraints.anchor= GridBagConstraints.WEST;
166 		labelConstraints.weightx= 1.0;
167 		labelConstraints.weighty= 0.0;
168 		labelConstraints.insets= new Insets(8, 8, 0, 8);
169 		getContentPane().add(fDescription, labelConstraints);
170 
171 		GridBagConstraints listConstraints = new GridBagConstraints();
172 		listConstraints.gridx= 0; listConstraints.gridy= 1;
173 		listConstraints.gridwidth= 4; listConstraints.gridheight= 1;
174 		listConstraints.fill= GridBagConstraints.BOTH;
175 		listConstraints.anchor= GridBagConstraints.CENTER;
176 		listConstraints.weightx= 1.0;
177 		listConstraints.weighty= 1.0;
178 		listConstraints.insets= new Insets(8, 8, 8, 8);
179 		getContentPane().add(fScrolledList, listConstraints);
180 		
181 		GridBagConstraints okConstraints= new GridBagConstraints();
182 		okConstraints.gridx= 2; okConstraints.gridy= 2;
183 		okConstraints.gridwidth= 1; okConstraints.gridheight= 1;
184 		okConstraints.anchor= java.awt.GridBagConstraints.EAST;
185 		okConstraints.insets= new Insets(0, 8, 8, 8);
186 		getContentPane().add(fOk, okConstraints);
187 
188 
189 		GridBagConstraints cancelConstraints = new GridBagConstraints();
190 		cancelConstraints.gridx= 3; cancelConstraints.gridy= 2;
191 		cancelConstraints.gridwidth= 1; cancelConstraints.gridheight= 1;
192 		cancelConstraints.anchor= java.awt.GridBagConstraints.EAST;
193 		cancelConstraints.insets= new Insets(0, 8, 8, 8);
194 		getContentPane().add(fCancel, cancelConstraints);
195 	}
196 	
197 	public void checkEnableOK(ListSelectionEvent e) {
198 		fOk.setEnabled(fList.getSelectedIndex() != -1);
199 	}
200 	
201 	public void okSelected() {
202 		fSelectedItem= (String)fList.getSelectedValue();
203 		dispose();
204 	}
205 	
206 	public boolean isEmpty() {
207 		return fList.getModel().getSize() == 0;
208 	}
209 	
210 	public void keySelectTestClass(char ch) {
211 		ListModel model= fList.getModel();
212 		if (!Character.isJavaIdentifierStart(ch))
213 			return;
214 		for (int i= 0; i < model.getSize(); i++) {
215 			String s= (String)model.getElementAt(i);
216 			if (TestCellRenderer.matchesKey(s, Character.toUpperCase(ch))) {
217 				fList.setSelectedIndex(i);
218 				fList.ensureIndexIsVisible(i);
219 				return;
220 			}
221 		}
222 		Toolkit.getDefaultToolkit().beep();
223 	}
224 	
225 	public String getSelectedItem() {
226 		return fSelectedItem;
227 	}
228 
229 	private Vector createTestList(TestCollector collector) {
230     		Enumeration each= collector.collectTests();
231     		Vector v= new Vector(200);
232     		Vector displayVector= new Vector(v.size());
233     		while(each.hasMoreElements()) {
234     			String s= (String)each.nextElement();
235     			v.addElement(s);
236     			displayVector.addElement(TestCellRenderer.displayString(s));
237     		}
238     		if (v.size() > 0)
239     			Sorter.sortStrings(displayVector, 0, displayVector.size()-1, new ParallelSwapper(v));
240     		return v;
241 	}
242 	
243 	private class ParallelSwapper implements Sorter.Swapper {
244 		Vector fOther;
245 		
246 		ParallelSwapper(Vector other) {
247 			fOther= other;
248 		}
249 		public void swap(Vector values, int left, int right) {
250 			Object tmp= values.elementAt(left); 
251 			values.setElementAt(values.elementAt(right), left); 
252 			values.setElementAt(tmp, right);
253 			Object tmp2= fOther.elementAt(left);
254 			fOther.setElementAt(fOther.elementAt(right), left);
255 			fOther.setElementAt(tmp2, right);
256 		}			
257 	}
258 }