View Javadoc

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