1
2
3
4
5
6
7
8
9
10
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 }