View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 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.teststeps.support;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Color;
17  import java.awt.Font;
18  import java.awt.event.ActionEvent;
19  import java.awt.event.ActionListener;
20  import java.awt.event.FocusAdapter;
21  import java.awt.event.FocusEvent;
22  
23  import javax.swing.BorderFactory;
24  import javax.swing.JCheckBoxMenuItem;
25  import javax.swing.JComponent;
26  import javax.swing.JPanel;
27  import javax.swing.event.CaretListener;
28  import javax.swing.event.PopupMenuListener;
29  import javax.swing.text.Document;
30  
31  import org.syntax.jedit.KeywordMap;
32  import org.syntax.jedit.tokenmarker.CTokenMarker;
33  import org.syntax.jedit.tokenmarker.GroovyTokenMarker;
34  import org.syntax.jedit.tokenmarker.Token;
35  
36  import com.eviware.soapui.model.settings.Settings;
37  import com.eviware.soapui.model.settings.SettingsListener;
38  import com.eviware.soapui.settings.UISettings;
39  import com.eviware.soapui.support.DocumentListenerAdapter;
40  import com.eviware.soapui.support.UISupport;
41  import com.eviware.soapui.support.components.JEditorStatusBar.JEditorStatusBarTarget;
42  import com.eviware.soapui.support.swing.JXEditAreaPopupMenu;
43  import com.eviware.soapui.support.xml.JXEditTextArea;
44  
45  /***
46   * Groovy editor wrapper
47   * 
48   * @author ole.matzura
49   */
50  
51  public class GroovyEditor extends JPanel implements JEditorStatusBarTarget
52  {
53  	private JXEditTextArea editArea;
54  	private GroovyEditorModel model;
55  	private InternalSettingsListener settingsListener;
56  	private GroovyDocumentListener groovyDocumentListener;
57  	private JCheckBoxMenuItem toggleLineNumbersMenuItem;
58  	private JPanel lineNumbersPanel;
59  
60  	public GroovyEditor( GroovyEditorModel model )
61  	{
62  		super( new BorderLayout() );
63  		this.model = model;
64  		
65  		editArea = new JXEditTextArea( new CTokenMarker( false, initKeywords() ) );
66  		editArea.setBorder( BorderFactory.createMatteBorder( 0, 2, 0, 0, Color.WHITE) );
67  		
68  		Settings settings = model.getSettings();
69  		editArea.setFont(UISupport.getEditorFont( settings ));
70  
71  		editArea.setText( model.getScript() );
72  		editArea.setCaretPosition(  0 );
73  		ActionListener runAction = model.getRunAction();
74  		if( runAction != null )
75  			editArea.getInputHandler().addKeyBinding( "A+ENTER", runAction );
76  		
77  		groovyDocumentListener = new GroovyDocumentListener();
78  		editArea.getDocument().addDocumentListener( groovyDocumentListener );
79  		
80  		settingsListener = new InternalSettingsListener();
81  		settings.addSettingsListener( settingsListener );
82  		
83  		add( editArea );
84  		add( buildLineNumbers(), BorderLayout.WEST );
85  		
86  		lineNumbersPanel.setVisible( settings.getBoolean( UISettings.SHOW_GROOVY_LINE_NUMBERS ) );
87  		
88  		addFocusListener( new FocusAdapter() {
89  
90  			public void focusGained( FocusEvent e )
91  			{
92  				editArea.requestFocusInWindow();
93  			}}
94  		);
95  		
96  		JXEditAreaPopupMenu popup = JXEditAreaPopupMenu.add( editArea );
97  		popup.add( editArea.getFindAndReplaceAction());
98  		popup.addSeparator();
99  		popup.add( editArea.getGoToLineAction() );
100 		toggleLineNumbersMenuItem = new JCheckBoxMenuItem( "Show Line Numbers", lineNumbersPanel.isVisible() );
101 		toggleLineNumbersMenuItem.setAccelerator( UISupport.getKeyStroke( "alt L" ) );
102 		toggleLineNumbersMenuItem.addActionListener( new ActionListener() {
103 
104 			public void actionPerformed( ActionEvent e )
105 			{
106 				lineNumbersPanel.setVisible( toggleLineNumbersMenuItem.isSelected() );
107 			}} );
108 		
109 		popup.add( toggleLineNumbersMenuItem );
110 	}
111 	
112 	private JComponent buildLineNumbers()
113 	{
114 		editArea.getInputHandler().addKeyBinding( "A+L", new ActionListener() {
115 
116 			public void actionPerformed( ActionEvent e )
117 			{
118 				lineNumbersPanel.setVisible( !lineNumbersPanel.isVisible() );
119 				toggleLineNumbersMenuItem.setSelected( lineNumbersPanel.isVisible() );
120 			}} );
121 		
122 		lineNumbersPanel = new LineNumbersPanel( editArea );
123 		return lineNumbersPanel;
124 	}
125 	
126 	public JXEditTextArea getEditArea()
127 	{
128 		return editArea;
129 	}
130 
131 	public void release()
132 	{
133 		model.getSettings().removeSettingsListener( settingsListener );
134 		model = null;
135 		editArea.getDocument().removeDocumentListener( groovyDocumentListener );
136 		editArea.getInputHandler().removeAllKeyBindings();
137 		editArea.getRightClickPopup().removeAll();
138 		for( PopupMenuListener listener : editArea.getRightClickPopup().getPopupMenuListeners() )
139 		{
140 			editArea.getRightClickPopup().removePopupMenuListener( listener );
141 		}
142 	}
143 
144 	public void selectError(String message)
145 	{
146 		int ix = message == null ? -1 : message.indexOf( "@ line " );
147 		if( ix >= 0 )
148 		{
149 			try
150 			{
151 				int ix2 = message.indexOf(',', ix);
152 				int line = ix2 == -1 ? Integer.parseInt(message.substring(ix + 6).trim()) : Integer.parseInt(message
153 						.substring(ix + 6, ix2).trim());
154 				int column = 0;
155 				if (ix2 != -1)
156 				{
157 					ix = message.indexOf("column ", ix2);
158 					if (ix >= 0)
159 					{
160 						ix2 = message.indexOf('.', ix);
161 						column = ix2 == -1 ? Integer.parseInt(message.substring(ix + 7).trim()) : Integer
162 								.parseInt(message.substring(ix + 7, ix2).trim());
163 					}
164 				}
165 				
166 				editArea.setCaretPosition(editArea.getLineStartOffset(line - 1) + column - 1);
167 			}
168 			catch (Exception ex)
169 			{
170 			}					
171 			
172 			editArea.requestFocus();
173 		}
174 	}
175 	
176 	private KeywordMap initKeywords()
177 	{
178 		KeywordMap keywords = GroovyTokenMarker.getKeywords();
179 		
180 		String[] kw = model.getKeywords();
181 		if( kw != null )
182 		{
183 			for( String keyword : kw )
184 				keywords.add(keyword,Token.KEYWORD2);
185 		}
186 		
187 		return keywords;
188 	}
189 	
190 	private final class GroovyDocumentListener extends DocumentListenerAdapter
191 	{
192 		public void update(Document document)
193 		{
194 			GroovyEditor.this.model.setScript( editArea.getText() );
195 		}
196 	}
197 
198 	private final class InternalSettingsListener implements SettingsListener
199 	{
200 		public void settingChanged(String name, String newValue, String oldValue)
201 		{
202 			if( name.equals( UISettings.EDITOR_FONT ))
203 			{
204 				editArea.setFont( Font.decode( newValue ));
205 				invalidate();
206 			}
207 		}
208 	}
209 
210 	public void addCaretListener( CaretListener listener )
211 	{
212 		editArea.addCaretListener( listener );
213 	}
214 
215 	public int getCaretPosition()
216 	{
217 		return editArea.getCaretPosition();
218 	}
219 
220 	public int getLineOfOffset( int offset ) throws Exception
221 	{
222 		return editArea.getLineOfOffset( offset );
223 	}
224 
225 	public int getLineStartOffset( int line ) throws Exception
226 	{
227 		return editArea.getLineStartOffset( line );
228 	}
229 
230 	public void removeCaretListener( CaretListener listener )
231 	{
232 		editArea.removeCaretListener( listener );
233 	}
234 }