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