001: /*
002: * soapUI, copyright (C) 2004-2007 eviware.com
003: *
004: * soapUI is free software; you can redistribute it and/or modify it under the
005: * terms of version 2.1 of the GNU Lesser General Public License as published by
006: * the Free Software Foundation.
007: *
008: * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009: * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: * See the GNU Lesser General Public License for more details at gnu.org.
011: */
012:
013: package com.eviware.soapui.impl.wsdl.panels.request.components.editor.views.source;
014:
015: import java.awt.Dimension;
016: import java.awt.Toolkit;
017: import java.awt.event.ActionEvent;
018: import java.awt.event.MouseAdapter;
019: import java.awt.event.MouseEvent;
020: import java.beans.PropertyChangeListener;
021:
022: import javax.swing.AbstractAction;
023: import javax.swing.Action;
024: import javax.swing.DefaultListModel;
025: import javax.swing.JComponent;
026: import javax.swing.JList;
027: import javax.swing.JPopupMenu;
028: import javax.swing.JScrollPane;
029: import javax.swing.JSplitPane;
030: import javax.swing.SwingUtilities;
031: import javax.swing.text.Document;
032:
033: import com.eviware.soapui.impl.wsdl.panels.request.components.editor.XmlEditor;
034: import com.eviware.soapui.impl.wsdl.panels.request.components.editor.XmlLocation;
035: import com.eviware.soapui.impl.wsdl.panels.request.components.editor.support.ValidationError;
036: import com.eviware.soapui.impl.wsdl.panels.request.components.editor.views.AbstractEditorView;
037: import com.eviware.soapui.support.DocumentListenerAdapter;
038: import com.eviware.soapui.support.UISupport;
039: import com.eviware.soapui.support.swing.SoapUISplitPaneUI;
040: import com.eviware.soapui.support.xml.JXEditTextArea;
041: import com.eviware.soapui.support.xml.actions.FormatXmlAction;
042: import com.eviware.soapui.support.xml.actions.LoadXmlTextAreaAction;
043: import com.eviware.soapui.support.xml.actions.SaveXmlTextAreaAction;
044:
045: /**
046: * Default "XML" source editor view in soapUI
047: *
048: * @author ole.matzura
049: */
050:
051: public class XmlSourceEditorView extends AbstractEditorView implements
052: PropertyChangeListener {
053: private JXEditTextArea editArea;
054: private ValidateMessageXmlAction validateXmlAction;
055: private JSplitPane splitter;
056: private JScrollPane errorScrollPane;
057: private DefaultListModel errorListModel;
058: private FormatXmlAction formatXmlAction;
059: private SaveXmlTextAreaAction saveXmlTextAreaAction;
060: private boolean updating;
061: private JPopupMenu editorPopup;
062: public boolean isLocating;
063: private JScrollPane editorScrollPane;
064: private LoadXmlTextAreaAction loadXmlTextAreaAction;
065: private JPopupMenu inputPopup;
066:
067: public XmlSourceEditorView(XmlEditor xmlEditor) {
068: super ("XML", xmlEditor);
069: }
070:
071: protected void buildUI() {
072: editArea = JXEditTextArea.createXmlEditor();
073: editArea.setMinimumSize(new Dimension(50, 50));
074: editArea.setCaretPosition(0);
075: editArea.setDiscardEditsOnSet(false);
076: editArea.setEnabled(false);
077:
078: errorListModel = new DefaultListModel();
079: JList list = new JList(errorListModel);
080: list.addMouseListener(new ValidationListMouseAdapter(list,
081: editArea));
082: errorScrollPane = new JScrollPane(list);
083: errorScrollPane.setVisible(false);
084:
085: splitter = new JSplitPane(JSplitPane.VERTICAL_SPLIT) {
086: public void requestFocus() {
087: SwingUtilities.invokeLater(new Runnable() {
088:
089: public void run() {
090: editArea.requestFocusInWindow();
091: }
092: });
093: }
094:
095: public boolean hasFocus() {
096: return editArea.hasFocus();
097: }
098: };
099:
100: splitter.setUI(new SoapUISplitPaneUI());
101: splitter.setDividerSize(0);
102: splitter.setOneTouchExpandable(true);
103:
104: editorPopup = new JPopupMenu();
105: buildPopup(editorPopup, editArea);
106:
107: editArea.setRightClickPopup(editorPopup);
108: editArea.getDocument().addDocumentListener(
109: new DocumentListenerAdapter() {
110:
111: public void update(Document document) {
112: if (!updating && getXmlDocument() != null) {
113: updating = true;
114: getXmlDocument().setXml(editArea.getText());
115: updating = false;
116: }
117: }
118: });
119:
120: editArea.getInputHandler().addKeyBinding("A+V",
121: validateXmlAction);
122: editArea.getInputHandler()
123: .addKeyBinding("A+F", formatXmlAction);
124: editArea.getInputHandler().addKeyBinding("C+S",
125: saveXmlTextAreaAction);
126:
127: editorScrollPane = new JScrollPane(editArea);
128: splitter.setTopComponent(editorScrollPane);
129: splitter.setBottomComponent(errorScrollPane);
130: splitter.setDividerLocation(1.0);
131: splitter.setBorder(null);
132: }
133:
134: public JScrollPane getEditorScrollPane() {
135: return editorScrollPane;
136: }
137:
138: protected void buildPopup(JPopupMenu inputPopup,
139: JXEditTextArea editArea) {
140: this .inputPopup = inputPopup;
141: validateXmlAction = new ValidateMessageXmlAction();
142: formatXmlAction = new FormatXmlAction(editArea);
143: saveXmlTextAreaAction = new SaveXmlTextAreaAction(editArea,
144: "Save");
145: loadXmlTextAreaAction = new LoadXmlTextAreaAction(editArea,
146: "Load");
147:
148: inputPopup.add(validateXmlAction);
149: inputPopup.add(formatXmlAction);
150: inputPopup.addSeparator();
151: inputPopup.add(editArea.getUndoAction());
152: inputPopup.add(editArea.getRedoAction());
153: inputPopup.add(editArea.createCopyAction());
154: inputPopup.add(editArea.createCutAction());
155: inputPopup.add(editArea.createPasteAction());
156: inputPopup.addSeparator();
157: inputPopup.add(editArea.getFindAndReplaceAction());
158: inputPopup.addSeparator();
159: inputPopup.add(saveXmlTextAreaAction);
160: inputPopup.add(loadXmlTextAreaAction);
161: }
162:
163: @Override
164: public void release() {
165: super .release();
166: inputPopup.removeAll();
167: }
168:
169: private final static class ValidationListMouseAdapter extends
170: MouseAdapter {
171: private final JList list;
172:
173: private final JXEditTextArea textArea;
174:
175: public ValidationListMouseAdapter(JList list,
176: JXEditTextArea textArea) {
177: this .list = list;
178: this .textArea = textArea;
179: }
180:
181: public void mouseClicked(MouseEvent e) {
182: if (e.getClickCount() < 2)
183: return;
184:
185: int ix = list.getSelectedIndex();
186: if (ix == -1)
187: return;
188:
189: Object obj = list.getModel().getElementAt(ix);
190: if (obj instanceof ValidationError) {
191: ValidationError error = (ValidationError) obj;
192: if (error.getLineNumber() >= 0) {
193: textArea
194: .setCaretPosition(textArea
195: .getLineStartOffset(error
196: .getLineNumber() - 1));
197: textArea.requestFocus();
198: } else
199: Toolkit.getDefaultToolkit().beep();
200: } else
201: Toolkit.getDefaultToolkit().beep();
202: }
203: }
204:
205: public JXEditTextArea getInputArea() {
206: getComponent();
207: return editArea;
208: }
209:
210: public void setEditable(boolean enabled) {
211: getComponent();
212: editArea.setEditable(enabled);
213: }
214:
215: protected ValidationError[] validateXml(String xml) {
216: return null;
217: }
218:
219: public class ValidateMessageXmlAction extends AbstractAction {
220: public ValidateMessageXmlAction() {
221: super ("Validate");
222: putValue(Action.ACCELERATOR_KEY, UISupport
223: .getKeyStroke("alt V"));
224: }
225:
226: public void actionPerformed(ActionEvent e) {
227: if (validate())
228: UISupport.showInfoMessage("Validation OK");
229: }
230: }
231:
232: public boolean activate(XmlLocation location) {
233: super .activate(location);
234:
235: if (location != null)
236: setLocation(location);
237:
238: editArea.requestFocus();
239:
240: return true;
241: }
242:
243: public JComponent getComponent() {
244: if (splitter == null)
245: buildUI();
246:
247: return splitter;
248: }
249:
250: public XmlLocation getLocation() {
251: return new XmlLocation(getCurrentLine(), getCurrentColumn());
252: }
253:
254: public void setLocation(XmlLocation location) {
255: if (location != null && location.getLine() >= 0) {
256: int offset = editArea
257: .getLineStartOffset(location.getLine());
258: try {
259: editArea
260: .setCaretPosition(offset + location.getColumn());
261: } catch (RuntimeException e) {
262: }
263: }
264: }
265:
266: public int getCurrentLine() {
267: if (editArea == null)
268: return -1;
269: return editArea.getCaretLine();
270: }
271:
272: public int getCurrentColumn() {
273: if (editArea == null)
274: return -1;
275: return editArea.getCaretColumn();
276: }
277:
278: public String getText() {
279: if (editArea == null)
280: return null;
281: return editArea.getText();
282: }
283:
284: public boolean validate() {
285: ValidationError[] errors = validateXml(editArea.getText());
286:
287: errorListModel.clear();
288: if (errors == null || errors.length == 0) {
289: splitter.setDividerLocation(1.0);
290: splitter.setDividerSize(0);
291: errorScrollPane.setVisible(false);
292: return true;
293: } else {
294: Toolkit.getDefaultToolkit().beep();
295: for (int c = 0; c < errors.length; c++) {
296: errorListModel.addElement(errors[c]);
297: }
298: errorScrollPane.setVisible(true);
299: splitter.setDividerLocation(0.8);
300: splitter.setDividerSize(10);
301: return false;
302: }
303: }
304:
305: protected void setXml(String xml) {
306: if (!updating) {
307: updating = true;
308:
309: if (xml == null) {
310: editArea.setText("");
311: editArea.setEnabled(false);
312: } else {
313: editArea.setEnabled(true);
314: editArea.setText(xml);
315: editArea.setCaretPosition(0);
316: }
317:
318: updating = false;
319: }
320: }
321:
322: public boolean saveDocument(boolean validate) {
323: return validate ? validate() : true;
324: }
325:
326: public void locationChanged(XmlLocation location) {
327: isLocating = true;
328: setLocation(location);
329: isLocating = false;
330: }
331:
332: public JPopupMenu getEditorPopup() {
333: return editorPopup;
334: }
335:
336: public boolean hasFocus() {
337: return editArea.hasFocus();
338: }
339:
340: public boolean isInspectable() {
341: return true;
342: }
343:
344: public String getViewId() {
345: return XmlSourceEditorFactory.VIEW_ID;
346: }
347: }
|