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.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 }