View Javadoc

    1   /*
    2    *  soapUI, copyright (C) 2004-2007 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.wsdl.panels.request.components.editor.views.source;
    14
    15  import java.awt.Dimension;
    16  import java.awt.Toolkit;
    17  import java.awt.event.ActionEvent;
    18  import java.awt.event.MouseAdapter;
    19  import java.awt.event.MouseEvent;
    20  import java.beans.PropertyChangeListener;
    21
    22  import javax.swing.AbstractAction;
    23  import javax.swing.Action;
    24  import javax.swing.DefaultListModel;
    25  import javax.swing.JComponent;
    26  import javax.swing.JList;
    27  import javax.swing.JPopupMenu;
    28  import javax.swing.JScrollPane;
    29  import javax.swing.JSplitPane;
    30  import javax.swing.SwingUtilities;
    31  import javax.swing.text.Document;
    32
    33  import com.eviware.soapui.impl.wsdl.panels.request.components.editor.XmlEditor;
    34  import com.eviware.soapui.impl.wsdl.panels.request.components.editor.XmlLocation;
    35  import com.eviware.soapui.impl.wsdl.panels.request.components.editor.support.ValidationError;
    36  import com.eviware.soapui.impl.wsdl.panels.request.components.editor.views.AbstractEditorView;
    37  import com.eviware.soapui.support.DocumentListenerAdapter;
    38  import com.eviware.soapui.support.UISupport;
    39  import com.eviware.soapui.support.swing.SoapUISplitPaneUI;
    40  import com.eviware.soapui.support.xml.JXEditTextArea;
    41  import com.eviware.soapui.support.xml.actions.FormatXmlAction;
    42  import com.eviware.soapui.support.xml.actions.LoadXmlTextAreaAction;
    43  import com.eviware.soapui.support.xml.actions.SaveXmlTextAreaAction;
    44
    45  /***
    46   * Default "XML" source editor view in soapUI
    47   *
    48   * @author ole.matzura
    49   */
    50
    51  public class XmlSourceEditorView extends AbstractEditorView implements PropertyChangeListener
    52  {
    53  	private JXEditTextArea editArea;
    54  	private ValidateMessageXmlAction validateXmlAction;
    55  	private JSplitPane splitter;
    56  	private JScrollPane errorScrollPane;
    57  	private DefaultListModel errorListModel;
    58  	private FormatXmlAction formatXmlAction;
    59  	private SaveXmlTextAreaAction saveXmlTextAreaAction;
    60  	private boolean updating;
    61  	private JPopupMenu editorPopup;
    62  	public boolean isLocating;
    63  	private JScrollPane editorScrollPane;
    64  	private LoadXmlTextAreaAction loadXmlTextAreaAction;
    65  	private JPopupMenu inputPopup;
    66
    67  	public XmlSourceEditorView( XmlEditor xmlEditor )
    68     {
    69     	super( "XML", xmlEditor );
    70     }
    71
    72  	protected void buildUI()
    73  	{
    74  		editArea = JXEditTextArea.createXmlEditor();
    75  		editArea.setMinimumSize(new Dimension(50, 50));
    76  		editArea.setCaretPosition(0);
    77  		editArea.setDiscardEditsOnSet(false);
    78  		editArea.setEnabled( false );
    79
    80  		errorListModel = new DefaultListModel();
    81  		JList list = new JList(errorListModel);
    82  		list.addMouseListener(new ValidationListMouseAdapter(list, editArea));
    83  		errorScrollPane = new JScrollPane(list);
    84  		errorScrollPane.setVisible(false);
    85
    86  		splitter = new JSplitPane(JSplitPane.VERTICAL_SPLIT)
    87  		{
    88  			public void requestFocus()
    89  			{
    90  				SwingUtilities.invokeLater( new Runnable() {
    91
    92  					public void run()
    93  					{
    94  						editArea.requestFocusInWindow();
    95  					}} );
    96  			}
    97
    98  			public boolean hasFocus()
    99  			{
    100 				return editArea.hasFocus();
    101 			}
    102 		};
    103
    104 		splitter.setUI( new SoapUISplitPaneUI() );
    105 		splitter.setDividerSize( 0 );
    106 		splitter.setOneTouchExpandable( true );
    107
    108 		editorPopup = new JPopupMenu();
    109 		buildPopup( editorPopup, editArea );
    110
    111 		editArea.setRightClickPopup(editorPopup);
    112 		editArea.getDocument().addDocumentListener(
    113 				new DocumentListenerAdapter() {
    114
    115 					public void update(Document document)
    116 					{
    117 						if( !updating && getXmlDocument() != null )
    118 						{
    119 							updating = true;
    120 							getXmlDocument().setXml( editArea.getText());
    121 							updating = false;
    122 						}
    123 					}
    124 				});
    125
    126 		editArea.getInputHandler().addKeyBinding("A+V", validateXmlAction);
    127 		editArea.getInputHandler().addKeyBinding("A+F", formatXmlAction);
    128 		editArea.getInputHandler().addKeyBinding("C+S", saveXmlTextAreaAction);
    129
    130 		editorScrollPane = new JScrollPane(editArea);
    131 		splitter.setTopComponent(editorScrollPane);
    132 		splitter.setBottomComponent(errorScrollPane);
    133 		splitter.setDividerLocation(1.0);
    134 		splitter.setBorder(null);
    135 	}
    136
    137 	public JScrollPane getEditorScrollPane()
    138 	{
    139 		return editorScrollPane;
    140 	}
    141
    142 	protected void buildPopup(JPopupMenu inputPopup, JXEditTextArea editArea )
    143 	{
    144 		this.inputPopup = inputPopup;
    145 		validateXmlAction = new ValidateMessageXmlAction( );
    146 		formatXmlAction = new FormatXmlAction(editArea);
    147 		saveXmlTextAreaAction = new SaveXmlTextAreaAction( editArea, "Save" );
    148 		loadXmlTextAreaAction = new LoadXmlTextAreaAction( editArea, "Load" );
    149
    150 		inputPopup.add(validateXmlAction);
    151 		inputPopup.add(formatXmlAction);
    152 		inputPopup.addSeparator();
    153 		inputPopup.add(editArea.getUndoAction());
    154 		inputPopup.add(editArea.getRedoAction());
    155 		inputPopup.add(editArea.createCopyAction());
    156 		inputPopup.add(editArea.createCutAction());
    157 		inputPopup.add(editArea.createPasteAction());
    158 		inputPopup.addSeparator();
    159 		inputPopup.add(editArea.getFindAndReplaceAction());
    160 		inputPopup.addSeparator();
    161 		inputPopup.add(saveXmlTextAreaAction);
    162 		inputPopup.add(loadXmlTextAreaAction);
    163 	}
    164
    165 	@Override
    166 	public void release()
    167 	{
    168 		super.release();
    169 		inputPopup.removeAll();
    170 	}
    171
    172 	private final static class ValidationListMouseAdapter extends MouseAdapter
    173 	{
    174 		private final JList list;
    175
    176 		private final JXEditTextArea textArea;
    177
    178 		public ValidationListMouseAdapter(JList list, JXEditTextArea textArea)
    179 		{
    180 			this.list = list;
    181 			this.textArea = textArea;
    182 		}
    183
    184 		public void mouseClicked(MouseEvent e)
    185 		{
    186 			if (e.getClickCount() < 2)
    187 				return;
    188
    189 			int ix = list.getSelectedIndex();
    190 			if (ix == -1)
    191 				return;
    192
    193 			Object obj = list.getModel().getElementAt(ix);
    194 			if (obj instanceof ValidationError)
    195 			{
    196 				ValidationError error = (ValidationError) obj;
    197 				if (error.getLineNumber() >= 0)
    198 				{
    199 					textArea.setCaretPosition(textArea.getLineStartOffset(error
    200 							.getLineNumber() - 1));
    201 					textArea.requestFocus();
    202 				}
    203 				else
    204 					Toolkit.getDefaultToolkit().beep();
    205 			}
    206 			else
    207 				Toolkit.getDefaultToolkit().beep();
    208 		}
    209 	}
    210
    211 	public JXEditTextArea getInputArea()
    212 	{
    213 		getComponent();
    214 		return editArea;
    215 	}
    216
    217 	public void setEditable(boolean enabled)
    218 	{
    219 		getComponent();
    220 	   editArea.setEditable( enabled );
    221 	}
    222
    223 	protected ValidationError[] validateXml( String xml )
    224 	{
    225 		return null;
    226 	}
    227
    228 	public class ValidateMessageXmlAction extends AbstractAction
    229 	{
    230 		public ValidateMessageXmlAction()
    231 		{
    232 			super( "Validate" );
    233 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "alt V" ));
    234 		}
    235
    236 		public void actionPerformed(ActionEvent e)
    237 		{
    238 			if( validate())
    239 				UISupport.showInfoMessage( "Validation OK" );
    240 		}
    241 	}
    242
    243    public boolean activate(XmlLocation location)
    244 	{
    245    	super.activate( location );
    246
    247    	if( location != null )
    248    		setLocation( location );
    249
    250    	editArea.requestFocus();
    251
    252    	return true;
    253 	}
    254
    255 	public JComponent getComponent()
    256 	{
    257 		if( splitter == null )
    258 			buildUI();
    259
    260 		return splitter;
    261 	}
    262
    263 	public XmlLocation getLocation()
    264 	{
    265 		return new XmlLocation( getCurrentLine(), getCurrentColumn() );
    266 	}
    267
    268 	public void setLocation(XmlLocation location)
    269 	{
    270 		if( location != null && location.getLine() >= 0 )
    271 		{
    272 			int offset = editArea.getLineStartOffset( location.getLine() );
    273 			try
    274 			{
    275 				editArea.setCaretPosition( offset + location.getColumn() );
    276 			}
    277 			catch( RuntimeException e )
    278 			{
    279 			}
    280 		}
    281 	}
    282
    283 	public int getCurrentLine()
    284 	{
    285 		if( editArea == null )
    286 			return -1;
    287 		return editArea.getCaretLine();
    288 	}
    289
    290 	public int getCurrentColumn()
    291 	{
    292 		if( editArea == null )
    293 			return -1;
    294 		return editArea.getCaretColumn();
    295 	}
    296
    297 	public String getText()
    298 	{
    299 		if( editArea == null )
    300 			return null;
    301 		return editArea.getText();
    302 	}
    303
    304 	public boolean validate()
    305 	{
    306 		ValidationError[] errors = validateXml( editArea.getText() );
    307
    308 		errorListModel.clear();
    309 		if( errors == null || errors.length == 0 )
    310 		{
    311 			splitter.setDividerLocation( 1.0 );
    312 			splitter.setDividerSize( 0 );
    313 		   errorScrollPane.setVisible( false );
    314 		   return true;
    315 		}
    316 		else
    317 		{
    318 			Toolkit.getDefaultToolkit().beep();
    319 		   for( int c = 0; c < errors.length; c++ )
    320 		   {
    321 		   	errorListModel.addElement( errors[c] );
    322 		   }
    323 		   errorScrollPane.setVisible( true );
    324 		   splitter.setDividerLocation( 0.8 );
    325 		   splitter.setDividerSize( 10 );
    326 		   return false;
    327 		}
    328 	}
    329
    330 	protected void setXml(String xml)
    331 	{
    332 		if( !updating )
    333 		{
    334 			updating = true;
    335
    336 			if( xml == null )
    337 			{
    338 				editArea.setText( "" );
    339 				editArea.setEnabled( false );
    340 			}
    341 			else
    342 			{
    343 				editArea.setEnabled( true );
    344 				editArea.setText( xml );
    345 				editArea.setCaretPosition( 0 );
    346 			}
    347
    348 			updating = false;
    349 		}
    350 	}
    351
    352 	public boolean saveDocument( boolean validate )
    353 	{
    354 		return validate ? validate() : true;
    355 	}
    356
    357 	public void locationChanged(XmlLocation location)
    358 	{
    359 		isLocating = true;
    360 		setLocation( location );
    361 		isLocating = false;
    362 	}
    363
    364 	public JPopupMenu getEditorPopup()
    365 	{
    366 		return editorPopup;
    367 	}
    368
    369 	public boolean hasFocus()
    370 	{
    371 		return editArea.hasFocus();
    372 	}
    373
    374 	public boolean isInspectable()
    375 	{
    376 		return true;
    377 	}
    378
    379 	public String getViewId()
    380 	{
    381 		return XmlSourceEditorFactory.VIEW_ID;
    382 	}
    383 }