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.Attachment;
51  import com.eviware.soapui.model.iface.Submit;
52  import com.eviware.soapui.model.iface.SubmitContext;
53  import com.eviware.soapui.model.iface.SubmitListener;
54  import com.eviware.soapui.model.iface.Request.SubmitException;
55  import com.eviware.soapui.model.iface.Submit.Status;
56  import com.eviware.soapui.settings.UISettings;
57  import com.eviware.soapui.support.StringUtils;
58  import com.eviware.soapui.support.UISupport;
59  import com.eviware.soapui.support.actions.ChangeSplitPaneOrientationAction;
60  import com.eviware.soapui.support.components.JEditorStatusBarWithProgress;
61  import com.eviware.soapui.support.components.JXToolBar;
62  import com.eviware.soapui.support.editor.views.xml.source.XmlSourceEditorView;
63  import com.eviware.soapui.support.editor.xml.XmlDocument;
64  import com.eviware.soapui.support.swing.SoapUISplitPaneUI;
65  import com.eviware.soapui.support.xml.JXEditTextArea;
66  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
67  
68  /***
69   * Abstract DesktopPanel for HttpRequests
70   * 
71   * @author Ole.Matzura
72   */
73  
74  public abstract class AbstractHttpRequestDesktopPanel<T extends ModelItem, T2 extends AbstractHttpRequestInterface<?>>
75  		extends ModelItemDesktopPanel<T> implements SubmitListener
76  {
77  	private final static Logger log = Logger.getLogger( AbstractHttpRequestDesktopPanel.class );
78  
79  	private JComponent endpointComponent;
80  	private JButton submitButton;
81  	private JButton cancelButton;
82  	private EndpointsComboBoxModel endpointsModel;
83  	private JEditorStatusBarWithProgress statusBar;
84  	private JButton splitButton;
85  	private Submit submit;
86  	private JSplitPane requestSplitPane;
87  	private MoveFocusAction moveFocusAction;
88  	private ClosePanelAction closePanelAction = new ClosePanelAction();
89  	private T2 request;
90  
91  	private ModelItemXmlEditor<?, ?> requestEditor;
92  	private ModelItemXmlEditor<?, ?> responseEditor;
93  
94  	private JTabbedPane requestTabs;
95  	private JPanel requestTabPanel;
96  	private JToggleButton tabsButton;
97  
98  	private boolean responseHasFocus;
99  	private SubmitAction submitAction;
100 	private boolean hasClosed;
101 
102 	public AbstractHttpRequestDesktopPanel( T modelItem, T2 request )
103 	{
104 		super( modelItem );
105 
106 		this.request = request;
107 
108 		init( request );
109 
110 		try
111 		{
112 			// required to avoid deadlock in UI when opening attachments inspector
113 			if( request.getAttachmentCount() > 0 && request.getOperation() != null )
114 			{
115 				request.getOperation().getInterface().getDefinitionContext().loadIfNecessary();
116 			}
117 		}
118 		catch( Exception e )
119 		{
120 			e.printStackTrace();
121 		}
122 	}
123 
124 	protected void init( T2 request )
125 	{
126 		this.endpointsModel = new EndpointsComboBoxModel( request );
127 
128 		request.addSubmitListener( this );
129 		request.addPropertyChangeListener( this );
130 
131 		add( buildContent(), BorderLayout.CENTER );
132 		add( buildToolbar(), BorderLayout.NORTH );
133 		add( buildStatusLabel(), BorderLayout.SOUTH );
134 
135 		setPreferredSize( new Dimension( 600, 500 ) );
136 
137 		addFocusListener( new FocusAdapter()
138 		{
139 
140 			@Override
141 			public void focusGained( FocusEvent e )
142 			{
143 				if( requestTabs.getSelectedIndex() == 1 || responseHasFocus )
144 					responseEditor.requestFocusInWindow();
145 				else
146 					requestEditor.requestFocusInWindow();
147 			}
148 		} );
149 	}
150 
151 	public final T2 getRequest()
152 	{
153 		return request;
154 	}
155 
156 	public final ModelItemXmlEditor<?, ?> getRequestEditor()
157 	{
158 		return requestEditor;
159 	}
160 
161 	public final ModelItemXmlEditor<?, ?> getResponseEditor()
162 	{
163 		return responseEditor;
164 	}
165 
166 	public Submit getSubmit()
167 	{
168 		return submit;
169 	}
170 
171 	protected JComponent buildStatusLabel()
172 	{
173 		statusBar = new JEditorStatusBarWithProgress();
174 		statusBar.setBorder( BorderFactory.createEmptyBorder( 1, 0, 0, 0 ) );
175 
176 		return statusBar;
177 	}
178 
179 	public JEditorStatusBarWithProgress getStatusBar()
180 	{
181 		return statusBar;
182 	}
183 
184 	protected JComponent buildContent()
185 	{
186 		requestSplitPane = UISupport.createHorizontalSplit();
187 		requestSplitPane.setResizeWeight( 0.5 );
188 		requestSplitPane.setBorder( null );
189 
190 		submitAction = new SubmitAction();
191 		submitButton = createActionButton( submitAction, true );
192 		submitButton.setEnabled( request.getEndpoint() != null && request.getEndpoint().trim().length() > 0 );
193 
194 		cancelButton = createActionButton( new CancelAction(), false );
195 		splitButton = createActionButton( new ChangeSplitPaneOrientationAction( requestSplitPane ), true );
196 
197 		tabsButton = new JToggleButton( new ChangeToTabsAction() );
198 		tabsButton.setPreferredSize( UISupport.TOOLBAR_BUTTON_DIMENSION );
199 
200 		moveFocusAction = new MoveFocusAction();
201 
202 		requestEditor = buildRequestEditor();
203 		responseEditor = buildResponseEditor();
204 
205 		requestTabs = new JTabbedPane();
206 		requestTabs.addChangeListener( new ChangeListener()
207 		{
208 
209 			public void stateChanged( ChangeEvent e )
210 			{
211 				SwingUtilities.invokeLater( new Runnable()
212 				{
213 
214 					public void run()
215 					{
216 						int ix = requestTabs.getSelectedIndex();
217 						if( ix == 0 )
218 							requestEditor.requestFocus();
219 						else if( ix == 1 && responseEditor != null )
220 							responseEditor.requestFocus();
221 					}
222 				} );
223 			}
224 		} );
225 
226 		requestTabPanel = UISupport.createTabPanel( requestTabs, true );
227 
228 		if( request.getSettings().getBoolean( UISettings.START_WITH_REQUEST_TABS ) )
229 		{
230 			requestTabs.addTab( "Request", requestEditor );
231 			if( responseEditor != null )
232 				requestTabs.addTab( "Response", responseEditor );
233 			splitButton.setEnabled( false );
234 			tabsButton.setSelected( true );
235 
236 			return requestTabPanel;
237 		}
238 		else
239 		{
240 			requestSplitPane.setTopComponent( requestEditor );
241 			requestSplitPane.setBottomComponent( responseEditor );
242 			requestSplitPane.setDividerLocation( 0.5 );
243 			return requestSplitPane;
244 		}
245 	}
246 
247 	public SubmitAction getSubmitAction()
248 	{
249 		return submitAction;
250 	}
251 
252 	protected abstract ModelItemXmlEditor<?, ?> buildResponseEditor();
253 
254 	protected abstract ModelItemXmlEditor<?, ?> buildRequestEditor();
255 
256 	protected JComponent buildToolbar()
257 	{
258 		endpointComponent = buildEndpointComponent();
259 
260 		JXToolBar toolbar = UISupport.createToolbar();
261 		toolbar.add( submitButton );
262 
263 		insertButtons( toolbar );
264 
265 		toolbar.add( cancelButton );
266 
267 		if( endpointComponent != null )
268 		{
269 			toolbar.addSeparator();
270 			toolbar.add( endpointComponent );
271 		}
272 
273 		toolbar.add( Box.createHorizontalGlue() );
274 		toolbar.add( tabsButton );
275 		toolbar.add( splitButton );
276 		toolbar.add( UISupport.createToolbarButton( new ShowOnlineHelpAction( getHelpUrl() ) ) );
277 
278 		return toolbar;
279 	}
280 
281 	protected JComponent buildEndpointComponent()
282 	{
283 		final JComboBox endpointCombo = new JComboBox( endpointsModel );
284 		endpointCombo.addPropertyChangeListener( this );
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( 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 || status == Status.ERROR )
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 				long attchmentsSize = 0;
600 				if( response.getAttachments().length > 0 )
601 				{
602 					for( Attachment att : response.getAttachments() )
603 					{
604 						attchmentsSize += att.getSize();
605 					}
606 				}
607 				message = "response time: " + response.getTimeTaken() + "ms ("
608 						+ ( response.getContentLength() + attchmentsSize ) + " bytes)";
609 				infoMessage = "Got response for [" + requestName + "] in " + response.getTimeTaken() + "ms ("
610 						+ ( response.getContentLength() + attchmentsSize ) + " bytes)";
611 
612 				if( !splitButton.isEnabled() )
613 					requestTabs.setSelectedIndex( 1 );
614 
615 				responseEditor.requestFocus();
616 			}
617 		}
618 
619 		logMessages( message, infoMessage );
620 
621 		if( getModelItem().getSettings().getBoolean( UISettings.AUTO_VALIDATE_RESPONSE ) )
622 			responseEditor.getSourceEditor().validate();
623 
624 		AbstractHttpRequestDesktopPanel.this.submit = null;
625 	}
626 
627 	protected void logMessages( String message, String infoMessage )
628 	{
629 		log.info( infoMessage );
630 		statusBar.setInfo( message );
631 	}
632 
633 	public boolean onClose( boolean canCancel )
634 	{
635 		if( canCancel )
636 		{
637 			if( submit != null && submit.getStatus() == Submit.Status.RUNNING )
638 			{
639 				Boolean retVal = UISupport.confirmOrCancel( "Cancel request before closing?", "Closing window" );
640 				if( retVal == null )
641 					return false;
642 
643 				if( retVal.booleanValue() && submit.getStatus() == Submit.Status.RUNNING )
644 				{
645 					submit.cancel();
646 				}
647 
648 				hasClosed = true;
649 			}
650 			else
651 			{
652 				request.removeSubmitListener( this );
653 			}
654 		}
655 		else if( submit != null && submit.getStatus() == Submit.Status.RUNNING )
656 		{
657 			submit.cancel();
658 			hasClosed = true;
659 		}
660 		else
661 		{
662 			request.removeSubmitListener( this );
663 		}
664 
665 		request.removePropertyChangeListener( this );
666 		requestEditor.saveDocument( false );
667 
668 		if( responseEditor != null )
669 			responseEditor.getParent().remove( responseEditor );
670 
671 		requestEditor.getParent().remove( requestEditor );
672 		requestSplitPane.removeAll();
673 
674 		return release();
675 	}
676 
677 	@Override
678 	protected boolean release()
679 	{
680 		endpointsModel.release();
681 		requestEditor.release();
682 
683 		if( responseEditor != null )
684 			responseEditor.release();
685 
686 		return super.release();
687 	}
688 
689 	public boolean dependsOn( ModelItem modelItem )
690 	{
691 		return request.dependsOn( modelItem );
692 	}
693 
694 	private final class ChangeToTabsAction extends AbstractAction
695 	{
696 		public ChangeToTabsAction()
697 		{
698 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/toggle_tabs.gif" ) );
699 			putValue( Action.SHORT_DESCRIPTION, "Toggles to tab-based layout" );
700 		}
701 
702 		public void actionPerformed( ActionEvent e )
703 		{
704 			if( splitButton.isEnabled() )
705 			{
706 				splitButton.setEnabled( false );
707 				showTabbedView( responseHasFocus );
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 	private void showTabbedView( boolean respFocus )
732 	{
733 		removeContent( requestSplitPane );
734 		setContent( requestTabPanel );
735 		requestTabs.addTab( "Request", requestEditor );
736 
737 		if( responseEditor != null )
738 			requestTabs.addTab( "Response", responseEditor );
739 
740 		if( respFocus )
741 		{
742 			requestTabs.setSelectedIndex( 1 );
743 			requestEditor.requestFocus();
744 		}
745 	}
746 
747 	public void focusResponseInTabbedView( boolean respFocus )
748 	{
749 		showTabbedView( respFocus );
750 		getResponseEditor().selectView( 2 );
751 	}
752 
753 	public void setContent( JComponent content )
754 	{
755 		add( content, BorderLayout.CENTER );
756 	}
757 
758 	public void removeContent( JComponent content )
759 	{
760 		remove( content );
761 	}
762 
763 	protected void onSubmit()
764 	{
765 		if( submit != null && submit.getStatus() == Submit.Status.RUNNING )
766 		{
767 			if( UISupport.confirm( "Cancel current request?", "Submit Request" ) )
768 			{
769 				submit.cancel();
770 			}
771 			else
772 				return;
773 		}
774 
775 		try
776 		{
777 			submit = doSubmit();
778 		}
779 		catch( SubmitException e1 )
780 		{
781 			SoapUI.logError( e1 );
782 		}
783 	}
784 
785 	protected void onCancel()
786 	{
787 		if( submit == null )
788 			return;
789 
790 		cancelButton.setEnabled( false );
791 		submit.cancel();
792 		setEnabled( true );
793 		submit = null;
794 	}
795 
796 	public boolean isHasClosed()
797 	{
798 		return hasClosed;
799 	}
800 
801 }