View Javadoc

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