001: /*
002: * soapUI, copyright (C) 2004-2007 eviware.com
003: *
004: * soapUI is free software; you can redistribute it and/or modify it under the
005: * terms of version 2.1 of the GNU Lesser General Public License as published by
006: * the Free Software Foundation.
007: *
008: * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009: * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: * See the GNU Lesser General Public License for more details at gnu.org.
011: */
012:
013: package com.eviware.soapui.impl.wsdl.panels.testcase;
014:
015: import java.awt.BorderLayout;
016: import java.awt.Component;
017: import java.awt.Insets;
018: import java.awt.Point;
019: import java.awt.dnd.Autoscroll;
020: import java.awt.event.ActionEvent;
021: import java.awt.event.KeyAdapter;
022: import java.awt.event.KeyEvent;
023: import java.awt.event.MouseAdapter;
024: import java.awt.event.MouseEvent;
025: import java.beans.PropertyChangeEvent;
026: import java.beans.PropertyChangeListener;
027:
028: import javax.swing.AbstractAction;
029: import javax.swing.AbstractListModel;
030: import javax.swing.Action;
031: import javax.swing.BorderFactory;
032: import javax.swing.JLabel;
033: import javax.swing.JList;
034: import javax.swing.JMenu;
035: import javax.swing.JPanel;
036: import javax.swing.JPopupMenu;
037: import javax.swing.JSeparator;
038: import javax.swing.ListCellRenderer;
039: import javax.swing.ListSelectionModel;
040: import javax.swing.event.PopupMenuEvent;
041: import javax.swing.event.PopupMenuListener;
042:
043: import com.eviware.soapui.SoapUI;
044: import com.eviware.soapui.config.TestStepConfig;
045: import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
046: import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
047: import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepFactory;
048: import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepRegistry;
049: import com.eviware.soapui.model.ModelItem;
050: import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
051: import com.eviware.soapui.model.testsuite.TestStep;
052: import com.eviware.soapui.support.UISupport;
053: import com.eviware.soapui.support.action.swing.ActionList;
054: import com.eviware.soapui.support.action.swing.ActionListBuilder;
055: import com.eviware.soapui.support.action.swing.ActionSupport;
056: import com.eviware.soapui.support.swing.AutoscrollSupport;
057:
058: /**
059: * Panel for displaying and editing a list of TestSteps
060: *
061: * @author Ole.Matzura
062: */
063:
064: public class TestStepList extends JPanel {
065: private TestStepListModel testStepListModel;
066: private JList testStepList;
067: private JPopupMenu testListPopup;
068: private JMenu appendStepMenu;
069: private final WsdlTestCase testCase;
070:
071: public TestStepList(WsdlTestCase testCase) {
072: super (new BorderLayout());
073: this .testCase = testCase;
074:
075: buildUI();
076: }
077:
078: public JList getTestStepList() {
079: return testStepList;
080: }
081:
082: private void buildUI() {
083: testStepListModel = new TestStepListModel();
084: testStepList = new TestStepJList(testStepListModel);
085: testStepList.setCellRenderer(new TestStepCellRenderer());
086: testStepList.setFixedCellHeight(22);
087: testStepList
088: .setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
089: testStepList.addKeyListener(new TestStepListKeyHandler());
090:
091: testStepList.addMouseListener(new StepListMouseListener());
092: testStepList.addMouseListener(new MouseAdapter() {
093: private int newIndex;
094: private int prevIndex;
095:
096: public void mouseClicked(MouseEvent e) {
097: if (e.getButton() != MouseEvent.BUTTON1)
098: return;
099:
100: newIndex = testStepList.locationToIndex(e.getPoint());
101:
102: if ((prevIndex == newIndex) & (prevIndex != -1)) {
103: testStepList.clearSelection();
104: newIndex = -1;
105: }
106:
107: prevIndex = newIndex;
108: }
109: });
110:
111: testListPopup = new JPopupMenu();
112: testListPopup.addSeparator();
113:
114: appendStepMenu = new JMenu("Append Step");
115:
116: WsdlTestStepRegistry registry = WsdlTestStepRegistry
117: .getInstance();
118: WsdlTestStepFactory[] factories = (WsdlTestStepFactory[]) registry
119: .getFactories();
120:
121: for (int c = 0; c < factories.length; c++) {
122: if (factories[c].canCreate())
123: appendStepMenu.add(new InsertTestStepAction(
124: factories[c]));
125: }
126:
127: testListPopup.add(appendStepMenu);
128:
129: testListPopup
130: .addPopupMenuListener(new StepListPopupMenuListener(
131: testCase));
132: testStepList.setComponentPopupMenu(testListPopup);
133:
134: add(testStepList, BorderLayout.CENTER);
135: }
136:
137: public void setEnabled(boolean enabled) {
138: testStepList.setEnabled(enabled);
139:
140: super .setEnabled(enabled);
141: }
142:
143: private final class TestStepListKeyHandler extends KeyAdapter {
144: public void keyPressed(KeyEvent e) {
145: if (e.getKeyChar() == KeyEvent.VK_ENTER) {
146: int ix = testStepList.getSelectedIndex();
147: if (ix != -1) {
148: TestStep testStep = (TestStep) testCase
149: .getTestStepAt(ix);
150: UISupport.selectAndShow(testStep);
151: e.consume();
152: }
153: } else {
154: int ix = testStepList.getSelectedIndex();
155: if (ix != -1) {
156: TestStep testStep = (TestStep) testCase
157: .getTestStepAt(ix);
158: ActionList actions = ActionListBuilder
159: .buildActions(testStep);
160: if (actions != null)
161: actions.dispatchKeyEvent(e);
162: }
163: }
164: }
165: }
166:
167: private final class StepListPopupMenuListener implements
168: PopupMenuListener {
169: private StepListPopupMenuListener(WsdlTestCase case1) {
170: super ();
171: }
172:
173: public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
174: while (testListPopup.getComponentCount() > 1)
175: testListPopup.remove(0);
176:
177: int ix = testStepList.getSelectedIndex();
178:
179: if (SoapUI.getTestMonitor().hasRunningLoadTest(testCase)) {
180: appendStepMenu.setEnabled(false);
181:
182: return;
183: }
184:
185: appendStepMenu.setEnabled(true);
186:
187: if (ix >= 0) {
188: testListPopup.insert(new JSeparator(), 0);
189: TestStep testStep = (TestStep) testCase
190: .getTestStepAt(ix);
191: ActionSupport.insertActions(ActionListBuilder
192: .buildActions(testStep), testListPopup, 0);
193: }
194: }
195:
196: public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
197: }
198:
199: public void popupMenuCanceled(PopupMenuEvent e) {
200: }
201: }
202:
203: private final class StepListMouseListener extends MouseAdapter {
204: public void mouseClicked(MouseEvent e) {
205: if (e.getClickCount() < 2) {
206: return;
207: }
208:
209: ModelItem modelItem = (ModelItem) testStepList
210: .getSelectedValue();
211: if (modelItem == null)
212: return;
213:
214: Action defaultAction = ActionListBuilder.buildActions(
215: modelItem).getDefaultAction();
216: if (defaultAction != null)
217: defaultAction.actionPerformed(new ActionEvent(
218: TestStepList.this , 0, null));
219: }
220: }
221:
222: /**
223: * Renderer which sets icon and wider border for teststeps
224: *
225: * @author Ole.Matzura
226: */
227:
228: private final static class TestStepCellRenderer extends JLabel
229: implements ListCellRenderer {
230: public TestStepCellRenderer() {
231: setOpaque(true);
232: setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
233: }
234:
235: public Component getListCellRendererComponent(JList list,
236: Object value, int index, boolean isSelected,
237: boolean cellHasFocus) {
238: WsdlTestStep testStep = (WsdlTestStep) value;
239:
240: if (testStep.isDisabled())
241: setText(testStep.getName() + " (disabled)");
242: else
243: setText(testStep.getName());
244:
245: setIcon(testStep.getIcon());
246:
247: if (isSelected) {
248: setBackground(list.getSelectionBackground());
249: setForeground(list.getSelectionForeground());
250: } else {
251: setBackground(list.getBackground());
252: setForeground(list.getForeground());
253: }
254:
255: setEnabled(list.isEnabled() && !testStep.isDisabled());
256:
257: String toolTipText = list.getToolTipText();
258: if (toolTipText == null)
259: setToolTipText(testStep.getDescription());
260: else
261: setToolTipText(toolTipText.length() == 0 ? null
262: : toolTipText);
263:
264: return this ;
265: }
266: }
267:
268: private class TestStepListModel extends AbstractListModel implements
269: PropertyChangeListener {
270: private TestStepListTestSuiteListener testStepListTestSuiteListener = new TestStepListTestSuiteListener();
271:
272: public TestStepListModel() {
273: for (int c = 0; c < getSize(); c++)
274: testCase.getTestStepAt(c).addPropertyChangeListener(
275: this );
276:
277: testCase.getTestSuite().addTestSuiteListener(
278: testStepListTestSuiteListener);
279: }
280:
281: public int getSize() {
282: return testCase.getTestStepCount();
283: }
284:
285: public Object getElementAt(int index) {
286: return testCase.getTestStepAt(index);
287: }
288:
289: public void propertyChange(PropertyChangeEvent arg0) {
290: int ix = testCase.getIndexOfTestStep((TestStep) arg0
291: .getSource());
292: if (ix == -1)
293: return;
294:
295: fireContentsChanged(this , ix, ix);
296: }
297:
298: public void release() {
299: testCase.getTestSuite().removeTestSuiteListener(
300: testStepListTestSuiteListener);
301:
302: for (int c = 0; c < getSize(); c++)
303: testCase.getTestStepAt(c).removePropertyChangeListener(
304: this );
305: }
306:
307: private class TestStepListTestSuiteListener extends
308: TestSuiteListenerAdapter {
309: public void testStepAdded(TestStep testStep, int ix) {
310: if (testStep.getTestCase() == testCase) {
311: testStep
312: .addPropertyChangeListener(TestStepListModel.this );
313: fireIntervalAdded(TestStepListModel.this , ix, ix);
314: }
315: }
316:
317: public void testStepRemoved(TestStep testStep, int ix) {
318: if (testStep.getTestCase() == testCase) {
319: testStep
320: .removePropertyChangeListener(TestStepListModel.this );
321: fireIntervalRemoved(TestStepListModel.this , ix, ix);
322: }
323: }
324:
325: @Override
326: public void testStepMoved(TestStep testStep, int fromIndex,
327: int offset) {
328: if (testStep.getTestCase() == testCase) {
329: fireContentsChanged(TestStepListModel.this ,
330: fromIndex, fromIndex + offset);
331: int selectedIndex = testStepList.getSelectedIndex();
332: if (selectedIndex == fromIndex) {
333: testStepList.setSelectedIndex(fromIndex
334: + offset);
335: } else if (selectedIndex < fromIndex
336: && selectedIndex >= fromIndex + offset) {
337: testStepList
338: .setSelectedIndex(selectedIndex + 1);
339: } else if (selectedIndex > fromIndex
340: && selectedIndex <= fromIndex + offset) {
341: testStepList
342: .setSelectedIndex(selectedIndex - 1);
343: }
344: }
345: }
346: }
347: }
348:
349: public class InsertTestStepAction extends AbstractAction {
350: private final WsdlTestStepFactory factory;
351:
352: public InsertTestStepAction(WsdlTestStepFactory factory) {
353: super (factory.getTestStepName());
354: putValue(Action.SHORT_DESCRIPTION, factory
355: .getTestStepDescription());
356: putValue(Action.SMALL_ICON, UISupport
357: .createImageIcon(factory.getTestStepIconPath()));
358: this .factory = factory;
359: }
360:
361: public void actionPerformed(ActionEvent e) {
362: String name = UISupport.prompt("Specify name for new step",
363: "Insert Step", factory.getTestStepName());
364: if (name != null) {
365: TestStepConfig newTestStepConfig = factory
366: .createNewTestStep(testCase, name);
367: if (newTestStepConfig != null) {
368: WsdlTestStep testStep = testCase
369: .addTestStep(newTestStepConfig);
370: UISupport.selectAndShow(testStep);
371: }
372: }
373: }
374: }
375:
376: public void setSelectedIndex(int i) {
377: testStepList.setSelectedIndex(i);
378: }
379:
380: public void setSelectedValue(TestStep testStep, boolean b) {
381: testStepList.setSelectedValue(testStep, true);
382: }
383:
384: public void release() {
385: testStepListModel.release();
386: }
387:
388: private static class TestStepJList extends JList implements
389: Autoscroll {
390: private AutoscrollSupport autoscrollSupport;
391:
392: public TestStepJList(TestStepListModel testStepListModel) {
393: super (testStepListModel);
394:
395: autoscrollSupport = new AutoscrollSupport(this , new Insets(
396: 10, 10, 10, 10));
397: }
398:
399: public void autoscroll(Point cursorLoc) {
400: autoscrollSupport.autoscroll(cursorLoc);
401: }
402:
403: public Insets getAutoscrollInsets() {
404: return autoscrollSupport.getAutoscrollInsets();
405: }
406: }
407: }
|