View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.support.panels;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Dimension;
17  import java.awt.event.ActionEvent;
18  import java.awt.event.FocusAdapter;
19  import java.awt.event.FocusEvent;
20  import java.awt.event.FocusListener;
21  import java.beans.PropertyChangeEvent;
22  
23  import javax.swing.AbstractAction;
24  import javax.swing.Action;
25  import javax.swing.BorderFactory;
26  import javax.swing.Box;
27  import javax.swing.JButton;
28  import javax.swing.JComboBox;
29  import javax.swing.JComponent;
30  import javax.swing.JPanel;
31  import javax.swing.JSplitPane;
32  import javax.swing.JTabbedPane;
33  import javax.swing.JToggleButton;
34  import javax.swing.SwingUtilities;
35  import javax.swing.event.ChangeEvent;
36  import javax.swing.event.ChangeListener;
37  
38  import org.apache.log4j.Logger;
39  
40  import com.eviware.soapui.SoapUI;
41  import com.eviware.soapui.impl.support.AbstractHttpRequest;
42  import com.eviware.soapui.impl.support.AbstractHttpRequestInterface;
43  import com.eviware.soapui.impl.support.EndpointsComboBoxModel;
44  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
45  import com.eviware.soapui.impl.support.components.ModelItemXmlEditor;
46  import com.eviware.soapui.impl.support.components.RequestMessageXmlEditor;
47  import com.eviware.soapui.impl.support.components.ResponseMessageXmlEditor;
48  import com.eviware.soapui.impl.wsdl.submit.transports.http.HttpResponse;
49  import com.eviware.soapui.model.ModelItem;
50  import com.eviware.soapui.model.iface.Submit;
51  import com.eviware.soapui.model.iface.SubmitContext;
52  import com.eviware.soapui.model.iface.SubmitListener;
53  import com.eviware.soapui.model.iface.Request.SubmitException;
54  import com.eviware.soapui.model.iface.Submit.Status;
55  import com.eviware.soapui.settings.UISettings;
56  import com.eviware.soapui.support.StringUtils;
57  import com.eviware.soapui.support.UISupport;
58  import com.eviware.soapui.support.actions.ChangeSplitPaneOrientationAction;
59  import com.eviware.soapui.support.components.JEditorStatusBarWithProgress;
60  import com.eviware.soapui.support.components.JXToolBar;
61  import com.eviware.soapui.support.editor.views.xml.source.XmlSourceEditorView;
62  import com.eviware.soapui.support.editor.xml.XmlDocument;
63  import com.eviware.soapui.support.swing.SoapUISplitPaneUI;
64  import com.eviware.soapui.support.xml.JXEditTextArea;
65  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
66  
67  /***
68   * Abstract DesktopPanel for HttpRequests
69   * 
70   * @author Ole.Matzura
71   */
72  
73  public abstract class AbstractHttpRequestDesktopPanel<T extends ModelItem, T2 extends AbstractHttpRequestInterface<?>>
74  		extends ModelItemDesktopPanel<T> implements SubmitListener
75  {
76  	private final static Logger log = Logger.getLogger(AbstractHttpRequestDesktopPanel.class);
77  
78  	private JComponent endpointComponent;
79  	private JButton submitButton;
80  	private JButton cancelButton;
81  	private EndpointsComboBoxModel endpointsModel;
82  	private JEditorStatusBarWithProgress statusBar;
83  	private JButton splitButton;
84  	private Submit submit;
85  	private JSplitPane requestSplitPane;
86  	private MoveFocusAction moveFocusAction;
87  	private ClosePanelAction closePanelAction = new ClosePanelAction();
88  	private T2 request;
89  
90  	private ModelItemXmlEditor<?, ?> requestEditor;
91  	private ModelItemXmlEditor<?, ?> responseEditor;
92  
93  	private JTabbedPane requestTabs;
94  	private JPanel requestTabPanel;
95  	private JToggleButton tabsButton;
96  
97  	private boolean responseHasFocus;
98  	private SubmitAction submitAction;
99  	private boolean hasClosed;
100 
101 	public AbstractHttpRequestDesktopPanel(T modelItem, T2 request)
102 	{
103 		super(modelItem);
104 
105 		this.request = request;
106 
107 		init(request);
108 
109 		try
110 		{
111 			// required to avoid deadlock in UI when opening attachments inspector
112 			if (request.getAttachmentCount() > 0 && request.getOperation() != null)
113 			{
114 				request.getOperation().getInterface().getDefinitionContext().loadIfNecessary();
115 			}
116 		}
117 		catch (Exception e)
118 		{
119 			e.printStackTrace();
120 		}
121 	}
122 
123 	protected void init(T2 request)
124 	{
125 		this.endpointsModel = new EndpointsComboBoxModel(request);
126 
127 		request.addSubmitListener(this);
128 		request.addPropertyChangeListener(this);
129 
130 		add(buildContent(), BorderLayout.CENTER);
131 		add(buildToolbar(), BorderLayout.NORTH);
132 		add(buildStatusLabel(), BorderLayout.SOUTH);
133 
134 		setPreferredSize(new Dimension(600, 500));
135 
136 		addFocusListener(new FocusAdapter()
137 		{
138 
139 			@Override
140 			public void focusGained(FocusEvent e)
141 			{
142 				if (requestTabs.getSelectedIndex() == 1 || responseHasFocus)
143 					responseEditor.requestFocusInWindow();
144 				else
145 					requestEditor.requestFocusInWindow();
146 			}
147 		});
148 	}
149 
150 	public final T2 getRequest()
151 	{
152 		return request;
153 	}
154 
155 	public final ModelItemXmlEditor<?, ?> getRequestEditor()
156 	{
157 		return requestEditor;
158 	}
159 
160 	public final ModelItemXmlEditor<?, ?> getResponseEditor()
161 	{
162 		return responseEditor;
163 	}
164 
165 	public Submit getSubmit()
166 	{
167 		return submit;
168 	}
169 
170 	protected JComponent buildStatusLabel()
171 	{
172 		statusBar = new JEditorStatusBarWithProgress();
173 		statusBar.setBorder(BorderFactory.createEmptyBorder(1, 0, 0, 0));
174 
175 		return statusBar;
176 	}
177 
178 	public JEditorStatusBarWithProgress getStatusBar()
179 	{
180 		return statusBar;
181 	}
182 
183 	protected JComponent buildContent()
184 	{
185 		requestSplitPane = UISupport.createHorizontalSplit();
186 		requestSplitPane.setResizeWeight(0.5);
187 		requestSplitPane.setBorder(null);
188 
189 		submitAction = new SubmitAction();
190 		submitButton = createActionButton(submitAction, true);
191 		submitButton.setEnabled(request.getEndpoint() != null && request.getEndpoint().trim().length() > 0);
192 
193 		cancelButton = createActionButton(new CancelAction(), false);
194 		splitButton = createActionButton(new ChangeSplitPaneOrientationAction(requestSplitPane), true);
195 
196 		tabsButton = new JToggleButton(new ChangeToTabsAction());
197 		tabsButton.setPreferredSize(UISupport.TOOLBAR_BUTTON_DIMENSION);
198 
199 		moveFocusAction = new MoveFocusAction();
200 
201 		requestEditor = buildRequestEditor();
202 		responseEditor = buildResponseEditor();
203 
204 		requestTabs = new JTabbedPane();
205 		requestTabs.addChangeListener(new ChangeListener()
206 		{
207 
208 			public void stateChanged(ChangeEvent e)
209 			{
210 				SwingUtilities.invokeLater(new Runnable()
211 				{
212 
213 					public void run()
214 					{
215 						int ix = requestTabs.getSelectedIndex();
216 						if (ix == 0)
217 							requestEditor.requestFocus();
218 						else if (ix == 1 && responseEditor != null)
219 							responseEditor.requestFocus();
220 					}
221 				});
222 			}
223 		});
224 
225 		requestTabPanel = UISupport.createTabPanel(requestTabs, true);
226 
227 		if (request.getSettings().getBoolean(UISettings.START_WITH_REQUEST_TABS))
228 		{
229 			requestTabs.addTab("Request", requestEditor);
230 			if (responseEditor != null)
231 				requestTabs.addTab("Response", responseEditor);
232 			splitButton.setEnabled(false);
233 			tabsButton.setSelected(true);
234 
235 			return requestTabPanel;
236 		}
237 		else
238 		{
239 			requestSplitPane.setTopComponent(requestEditor);
240 			requestSplitPane.setBottomComponent(responseEditor);
241 			requestSplitPane.setDividerLocation(0.5);
242 			return requestSplitPane;
243 		}
244 	}
245 
246 	public SubmitAction getSubmitAction()
247 	{
248 		return submitAction;
249 	}
250 
251 	protected abstract ModelItemXmlEditor<?, ?> buildResponseEditor();
252 
253 	protected abstract ModelItemXmlEditor<?, ?> buildRequestEditor();
254 
255 	protected JComponent buildToolbar()
256 	{
257 		endpointComponent = buildEndpointComponent();
258 
259 		JXToolBar toolbar = UISupport.createToolbar();
260 		toolbar.add(submitButton);
261 
262 		insertButtons(toolbar);
263 
264 		toolbar.add(cancelButton);
265 
266 		if (endpointComponent != null)
267 		{
268 			toolbar.addSeparator();
269 			toolbar.add(endpointComponent);
270 		}
271 
272 		toolbar.add(Box.createHorizontalGlue());
273 		toolbar.add(tabsButton);
274 		toolbar.add(splitButton);
275 		toolbar.add(UISupport.createToolbarButton(new ShowOnlineHelpAction(getHelpUrl())));
276 
277 		return toolbar;
278 	}
279 
280 	protected JComponent buildEndpointComponent()
281 	{
282 		final JComboBox endpointCombo = new JComboBox(endpointsModel);
283 		endpointCombo.addPropertyChangeListener(this);
284 		endpointCombo.setToolTipText(endpointsModel.getSelectedItem().toString());
285 
286 		return UISupport.addTooltipListener(endpointCombo, "- no endpoint set for request -");
287 	}
288 
289 	public void propertyChange(PropertyChangeEvent evt)
290 	{
291 		if (evt.getPropertyName().equals(AbstractHttpRequest.ENDPOINT_PROPERTY))
292 		{
293 			submitButton.setEnabled(submit == null && StringUtils.hasContent(request.getEndpoint()));
294 		}
295 
296 		super.propertyChange(evt);
297 	}
298 
299 
300 	public JButton getSubmitButton()
301 	{
302 		return submitButton;
303 	}
304 
305 	protected abstract String getHelpUrl();
306 
307 	protected abstract void insertButtons(JXToolBar toolbar);
308 
309 	public void setEnabled(boolean enabled)
310 	{
311 		if (endpointComponent != null)
312 			endpointComponent.setEnabled(enabled);
313 
314 		requestEditor.setEditable(enabled);
315 		if (responseEditor != null)
316 			responseEditor.setEditable(enabled);
317 
318 		submitButton.setEnabled(enabled && request.hasEndpoint());
319 
320 		statusBar.setIndeterminate(!enabled);
321 	}
322 
323 	public abstract class AbstractHttpRequestMessageEditor<T3 extends XmlDocument> extends
324 			RequestMessageXmlEditor<T2, T3>
325 	{
326 		private InputAreaFocusListener inputAreaFocusListener;
327 		private JXEditTextArea inputArea;
328 
329 		public AbstractHttpRequestMessageEditor(T3 document)
330 		{
331 			super(document, request);
332 
333 			XmlSourceEditorView<?> editor = getSourceEditor();
334 			if (editor != null)
335 			{
336 				inputArea = editor.getInputArea();
337 				inputArea.getInputHandler().addKeyBinding("A+ENTER", submitButton.getAction());
338 				inputArea.getInputHandler().addKeyBinding("A+X", cancelButton.getAction());
339 				inputArea.getInputHandler().addKeyBinding("AC+TAB", moveFocusAction);
340 				inputArea.getInputHandler().addKeyBinding("C+F4", closePanelAction);
341 
342 				inputAreaFocusListener = new InputAreaFocusListener(editor);
343 				inputArea.addFocusListener(inputAreaFocusListener);
344 			}
345 		}
346 
347 		@Override
348 		public void release()
349 		{
350 			super.release();
351 			if (inputArea != null)
352 				inputArea.removeFocusListener(inputAreaFocusListener);
353 		}
354 	}
355 
356 	public abstract class AbstractHttpResponseMessageEditor<T3 extends XmlDocument> extends
357 			ResponseMessageXmlEditor<T2, T3>
358 	{
359 		private JXEditTextArea inputArea;
360 		private ResultAreaFocusListener resultAreaFocusListener;
361 
362 		public AbstractHttpResponseMessageEditor(T3 document)
363 		{
364 			super(document, request);
365 
366 			XmlSourceEditorView<?> editor = getSourceEditor();
367 
368 			inputArea = editor.getInputArea();
369 			if (inputArea != null)
370 			{
371 				resultAreaFocusListener = new ResultAreaFocusListener(editor);
372 				inputArea.addFocusListener(resultAreaFocusListener);
373 
374 				inputArea.getInputHandler().addKeyBinding("A+ENTER", submitButton.getAction());
375 				inputArea.getInputHandler().addKeyBinding("A+X", cancelButton.getAction());
376 				inputArea.getInputHandler().addKeyBinding("AC+TAB", moveFocusAction);
377 				inputArea.getInputHandler().addKeyBinding("C+F4", closePanelAction);
378 			}
379 		}
380 
381 		@Override
382 		public void release()
383 		{
384 			super.release();
385 
386 			if (inputArea != null)
387 				inputArea.removeFocusListener(resultAreaFocusListener);
388 		}
389 	}
390 
391 	protected final class InputAreaFocusListener implements FocusListener
392 	{
393 		private final XmlSourceEditorView<?> sourceEditor;
394 
395 		public InputAreaFocusListener(XmlSourceEditorView<?> editor)
396 		{
397 			this.sourceEditor = editor;
398 		}
399 
400 		public void focusGained(FocusEvent e)
401 		{
402 			responseHasFocus = false;
403 
404 			statusBar.setTarget(sourceEditor.getInputArea());
405 			if (!splitButton.isEnabled())
406 			{
407 				requestTabs.setSelectedIndex(0);
408 				return;
409 			}
410 
411 			if (getModelItem().getSettings().getBoolean(UISettings.NO_RESIZE_REQUEST_EDITOR))
412 				return;
413 
414 			// dont resize if split has been dragged
415 			if (requestSplitPane.getUI() instanceof SoapUISplitPaneUI
416 					&& ((SoapUISplitPaneUI) requestSplitPane.getUI()).hasBeenDragged())
417 				return;
418 
419 			int pos = requestSplitPane.getDividerLocation();
420 			if (pos >= 600)
421 				return;
422 			if (requestSplitPane.getMaximumDividerLocation() > 700)
423 				requestSplitPane.setDividerLocation(600);
424 			else
425 				requestSplitPane.setDividerLocation(0.8);
426 		}
427 
428 		public void focusLost(FocusEvent e)
429 		{
430 		}
431 	}
432 
433 	protected final class ResultAreaFocusListener implements FocusListener
434 	{
435 		private final XmlSourceEditorView<?> sourceEditor;
436 
437 		public ResultAreaFocusListener(XmlSourceEditorView<?> editor)
438 		{
439 			this.sourceEditor = editor;
440 		}
441 
442 		public void focusGained(FocusEvent e)
443 		{
444 			responseHasFocus = true;
445 
446 			statusBar.setTarget(sourceEditor.getInputArea());
447 			if (!splitButton.isEnabled())
448 			{
449 				requestTabs.setSelectedIndex(1);
450 				return;
451 			}
452 
453 			if (request.getSettings().getBoolean(UISettings.NO_RESIZE_REQUEST_EDITOR))
454 				return;
455 
456 			// dont resize if split has been dragged or result is empty
457 			if (requestSplitPane.getUI() instanceof SoapUISplitPaneUI
458 					&& ((SoapUISplitPaneUI) requestSplitPane.getUI()).hasBeenDragged() || request.getResponse() == null)
459 				return;
460 
461 			int pos = requestSplitPane.getDividerLocation();
462 			int maximumDividerLocation = requestSplitPane.getMaximumDividerLocation();
463 			if (pos + 600 < maximumDividerLocation)
464 				return;
465 
466 			if (maximumDividerLocation > 700)
467 				requestSplitPane.setDividerLocation(maximumDividerLocation - 600);
468 			else
469 				requestSplitPane.setDividerLocation(0.2);
470 		}
471 
472 		public void focusLost(FocusEvent e)
473 		{
474 		}
475 	}
476 
477 	public class SubmitAction extends AbstractAction
478 	{
479 		public SubmitAction()
480 		{
481 			putValue(Action.SMALL_ICON, UISupport.createImageIcon("/submit_request.gif"));
482 			putValue(Action.SHORT_DESCRIPTION, "Submit request to specified endpoint URL");
483 			putValue(Action.ACCELERATOR_KEY, UISupport.getKeyStroke("alt ENTER"));
484 		}
485 
486 		public void actionPerformed(ActionEvent e)
487 		{
488 			onSubmit();
489 		}
490 	}
491 
492 	protected abstract Submit doSubmit() throws SubmitException;
493 
494 	private class CancelAction extends AbstractAction
495 	{
496 		public CancelAction()
497 		{
498 			super();
499 			putValue(Action.SMALL_ICON, UISupport.createImageIcon("/cancel_request.gif"));
500 			putValue(Action.SHORT_DESCRIPTION, "Aborts ongoing request");
501 			putValue(Action.ACCELERATOR_KEY, UISupport.getKeyStroke("alt X"));
502 		}
503 
504 		public void actionPerformed(ActionEvent e)
505 		{
506 			onCancel();
507 		}
508 	}
509 
510 	private class ClosePanelAction extends AbstractAction
511 	{
512 		public void actionPerformed(ActionEvent e)
513 		{
514 			SoapUI.getDesktop().closeDesktopPanel(getModelItem());
515 		}
516 	}
517 
518 	private class MoveFocusAction extends AbstractAction
519 	{
520 		public void actionPerformed(ActionEvent e)
521 		{
522 			if (requestEditor.hasFocus())
523 			{
524 				responseEditor.requestFocus();
525 			}
526 			else
527 			{
528 				requestEditor.requestFocus();
529 			}
530 		}
531 	}
532 
533 	public boolean beforeSubmit(Submit submit, SubmitContext context)
534 	{
535 		if (submit.getRequest() != request)
536 			return true;
537 
538 		if (getModelItem().getSettings().getBoolean(UISettings.AUTO_VALIDATE_REQUEST))
539 		{
540 			boolean result = requestEditor.saveDocument(true);
541 			if (!result && getModelItem().getSettings().getBoolean(UISettings.ABORT_ON_INVALID_REQUEST))
542 			{
543 				statusBar.setInfo("Cancelled request due to invalid content");
544 				return false;
545 			}
546 		}
547 		else
548 		{
549 			if (requestEditor != null)
550 				requestEditor.saveDocument(false);
551 		}
552 
553 		setEnabled(false);
554 		cancelButton.setEnabled(AbstractHttpRequestDesktopPanel.this.submit != null);
555 		return true;
556 	}
557 
558 	public void afterSubmit(Submit submit, SubmitContext context)
559 	{
560 		if (submit.getRequest() != request)
561 			return;
562 
563 		Status status = submit.getStatus();
564 		HttpResponse response = (HttpResponse) submit.getResponse();
565 		if (status == Status.FINISHED)
566 		{
567 			request.setResponse(response, context);
568 		}
569 
570 		if (hasClosed)
571 		{
572 			request.removeSubmitListener(this);
573 			return;
574 		}
575 
576 		cancelButton.setEnabled(false);
577 		setEnabled(true);
578 
579 		String message = null;
580 		String infoMessage = null;
581 		String requestName = request.getOperation() == null ? request.getName() : request.getOperation().getInterface()
582 				.getName()
583 				+ "." + request.getOperation().getName() + ":" + request.getName();
584 
585 		if (status == Status.CANCELED)
586 		{
587 			message = "CANCELED";
588 			infoMessage = "[" + requestName + "] - CANCELED";
589 		}
590 		else
591 		{
592 			if (status == Status.ERROR || response == null)
593 			{
594 				message = "Error getting response; " + submit.getError();
595 				infoMessage = "Error getting response for [" + requestName + "]; " + submit.getError();
596 			}
597 			else
598 			{
599 				message = "response time: " + response.getTimeTaken() + "ms (" + response.getContentLength() + " bytes)";
600 				infoMessage = "Got response for [" + requestName + "] in " + response.getTimeTaken() + "ms ("
601 						+ response.getContentLength() + " bytes)";
602 
603 				if (!splitButton.isEnabled())
604 					requestTabs.setSelectedIndex(1);
605 
606 				responseEditor.requestFocus();
607 			}
608 		}
609 
610 		logMessages(message, infoMessage);
611 
612 		if (getModelItem().getSettings().getBoolean(UISettings.AUTO_VALIDATE_RESPONSE))
613 			responseEditor.getSourceEditor().validate();
614 
615 		AbstractHttpRequestDesktopPanel.this.submit = null;
616 	}
617 
618 	protected void logMessages(String message, String infoMessage)
619 	{
620 		log.info(infoMessage);
621 		statusBar.setInfo(message);
622 	}
623 
624 	public boolean onClose(boolean canCancel)
625 	{
626 		if (canCancel)
627 		{
628 			if (submit != null && submit.getStatus() == Submit.Status.RUNNING)
629 			{
630 				Boolean retVal = UISupport.confirmOrCancel("Cancel request before closing?", "Closing window");
631 				if (retVal == null)
632 					return false;
633 
634 				if (retVal.booleanValue() && submit.getStatus() == Submit.Status.RUNNING)
635 				{
636 					submit.cancel();
637 				}
638 
639 				hasClosed = true;
640 			}
641 			else
642 			{
643 				request.removeSubmitListener(this);
644 			}
645 		}
646 		else if (submit != null && submit.getStatus() == Submit.Status.RUNNING)
647 		{
648 			submit.cancel();
649 			hasClosed = true;
650 		}
651 		else
652 		{
653 			request.removeSubmitListener(this);
654 		}
655 
656 		request.removePropertyChangeListener(this);
657 		requestEditor.saveDocument(false);
658 
659 		if (responseEditor != null)
660 			responseEditor.getParent().remove(responseEditor);
661 
662 		requestEditor.getParent().remove(requestEditor);
663 		requestSplitPane.removeAll();
664 
665 		return release();
666 	}
667 
668 	@Override
669 	protected boolean release()
670 	{
671 		endpointsModel.release();
672 		requestEditor.release();
673 
674 		if (responseEditor != null)
675 			responseEditor.release();
676 
677 		return super.release();
678 	}
679 
680 	public boolean dependsOn(ModelItem modelItem)
681 	{
682 		return request.dependsOn(modelItem);
683 	}
684 
685 	private final class ChangeToTabsAction extends AbstractAction
686 	{
687 		public ChangeToTabsAction()
688 		{
689 			putValue(Action.SMALL_ICON, UISupport.createImageIcon("/toggle_tabs.gif"));
690 			putValue(Action.SHORT_DESCRIPTION, "Toggles to tab-based layout");
691 		}
692 
693 		public void actionPerformed(ActionEvent e)
694 		{
695 			if (splitButton.isEnabled())
696 			{
697 				splitButton.setEnabled(false);
698 				removeContent(requestSplitPane);
699 				setContent(requestTabPanel);
700 				requestTabs.addTab("Request", requestEditor);
701 
702 				if (responseEditor != null)
703 					requestTabs.addTab("Response", responseEditor);
704 
705 				if (responseHasFocus)
706 				{
707 					requestTabs.setSelectedIndex(1);
708 					requestEditor.requestFocus();
709 				}
710 			}
711 			else
712 			{
713 				int selectedIndex = requestTabs.getSelectedIndex();
714 
715 				splitButton.setEnabled(true);
716 				removeContent(requestTabPanel);
717 				setContent(requestSplitPane);
718 				requestSplitPane.setTopComponent(requestEditor);
719 				if (responseEditor != null)
720 					requestSplitPane.setBottomComponent(responseEditor);
721 				requestSplitPane.setDividerLocation(0.5);
722 
723 				if (selectedIndex == 0 || responseEditor == null)
724 					requestEditor.requestFocus();
725 				else
726 					responseEditor.requestFocus();
727 			}
728 
729 			revalidate();
730 		}
731 	}
732 
733 	public void setContent(JComponent content)
734 	{
735 		add(content, BorderLayout.CENTER);
736 	}
737 
738 	public void removeContent(JComponent content)
739 	{
740 		remove(content);
741 	}
742 
743 	protected void onSubmit()
744 	{
745 		if (submit != null && submit.getStatus() == Submit.Status.RUNNING)
746 		{
747 			if (UISupport.confirm("Cancel current request?", "Submit Request"))
748 			{
749 				submit.cancel();
750 			}
751 			else
752 				return;
753 		}
754 
755 		try
756 		{
757 			submit = doSubmit();
758 		}
759 		catch (SubmitException e1)
760 		{
761 			SoapUI.logError(e1);
762 		}
763 	}
764 
765 	protected void onCancel()
766 	{
767 		if (submit == null)
768 			return;
769 
770 		cancelButton.setEnabled(false);
771 		submit.cancel();
772 		setEnabled(true);
773 		submit = null;
774 	}
775 
776 	public boolean isHasClosed()
777 	{
778 		return hasClosed;
779 	}
780 
781 }