1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.panels.teststeps.support;
14
15 import com.eviware.soapui.StandaloneSoapUICore;
16 import com.eviware.soapui.model.settings.Settings;
17 import com.eviware.soapui.model.settings.SettingsListener;
18 import com.eviware.soapui.settings.UISettings;
19 import com.eviware.soapui.support.DocumentListenerAdapter;
20 import com.eviware.soapui.support.UISupport;
21 import com.eviware.soapui.support.actions.FindAndReplaceDialog;
22 import com.eviware.soapui.support.actions.FindAndReplaceable;
23 import com.eviware.soapui.support.components.JEditorStatusBar.JEditorStatusBarTarget;
24 import com.eviware.soapui.support.swing.RSyntaxAreaPopupMenu;
25 import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
26 import org.fife.ui.rsyntaxtextarea.SyntaxScheme;
27 import org.fife.ui.rtextarea.LineNumberBorder;
28 import org.fife.ui.rtextarea.RTextScrollPane;
29 import org.syntax.jedit.KeywordMap;
30 import org.syntax.jedit.tokenmarker.GroovyTokenMarker;
31 import org.syntax.jedit.tokenmarker.Token;
32
33 import javax.swing.*;
34 import javax.swing.event.CaretListener;
35 import javax.swing.text.Document;
36 import java.awt.*;
37 import java.awt.event.ActionEvent;
38 import java.awt.event.ActionListener;
39 import java.awt.event.FocusAdapter;
40 import java.awt.event.FocusEvent;
41
42 /***
43 * Groovy editor wrapper
44 *
45 * @author ole.matzura
46 */
47
48 public class GroovyEditor extends JPanel implements JEditorStatusBarTarget
49 {
50 private RSyntaxTextArea editArea;
51 private GroovyEditorModel model;
52 private InternalSettingsListener settingsListener;
53 private GroovyDocumentListener groovyDocumentListener;
54 private RTextScrollPane scrollPane;
55 private JCheckBoxMenuItem toggleLineNumbersMenuItem;
56
57
58 public GroovyEditor( GroovyEditorModel model )
59 {
60 super( new BorderLayout() );
61 this.model = model;
62
63 Settings settings = model.getSettings();
64 Font editorFont = UISupport.getEditorFont( settings );
65
66 editArea = new RSyntaxTextArea();
67 editArea.restoreDefaultSyntaxHighlightingColorScheme();
68
69 setEditorFont( editorFont );
70
71 editArea.setSyntaxEditingStyle( RSyntaxTextArea.GROOVY_SYNTAX_STYLE );
72 editArea.setBorder( BorderFactory.createMatteBorder( 0, 2, 0, 0, Color.WHITE ) );
73
74 editArea.setText( model.getScript() );
75 editArea.setCaretPosition( 0 );
76 editArea.setCurrentLineHighlightEnabled( false );
77 Action runAction = model.getRunAction();
78 if( runAction != null )
79 {
80 editArea.getInputMap().put( KeyStroke.getKeyStroke( "alt ENTER" ), "run-action" );
81 editArea.getActionMap().put( "run-action", runAction );
82 }
83
84 groovyDocumentListener = new GroovyDocumentListener();
85 editArea.getDocument().addDocumentListener( groovyDocumentListener );
86
87 settingsListener = new InternalSettingsListener();
88 settings.addSettingsListener( settingsListener );
89
90 scrollPane = new RTextScrollPane( 500, 300, editArea, true );
91 add( scrollPane );
92
93 UISupport.addPreviewCorner( scrollPane, true );
94
95 addFocusListener( new FocusAdapter()
96 {
97 public void focusGained( FocusEvent e )
98 {
99 editArea.requestFocusInWindow();
100 }
101 }
102 );
103
104 RSyntaxAreaPopupMenu popup = RSyntaxAreaPopupMenu.add( editArea );
105 popup.add( new FindAndReplaceDialog( new RSyntaxTextAreaFindAndReplaceable() ) );
106 popup.addSeparator();
107 popup.add( new GoToLineAction() );
108
109 toggleLineNumbersMenuItem = new JCheckBoxMenuItem( "Show Line Numbers", scrollPane.areLineNumbersEnabled() );
110 toggleLineNumbersMenuItem.setAccelerator( UISupport.getKeyStroke( "alt L" ) );
111 toggleLineNumbersMenuItem.addActionListener( new ActionListener()
112 {
113 public void actionPerformed( ActionEvent e )
114 {
115 enableLineNumbers( toggleLineNumbersMenuItem.isSelected() );
116 }
117 } );
118
119 editArea.getInputMap().put( KeyStroke.getKeyStroke( "alt L" ), new AbstractAction()
120 {
121 public void actionPerformed( ActionEvent e )
122 {
123 enableLineNumbers( !scrollPane.areLineNumbersEnabled() );
124 }
125 } );
126
127 popup.add( toggleLineNumbersMenuItem );
128 editArea.setComponentPopupMenu( popup );
129
130 enableLineNumbers( settings.getBoolean( UISettings.SHOW_GROOVY_LINE_NUMBERS ) );
131 }
132
133 public void enableLineNumbers( boolean enable )
134 {
135 scrollPane.setLineNumbersEnabled( enable );
136 try
137 {
138 if( scrollPane.areLineNumbersEnabled() )
139 ( (LineNumberBorder) scrollPane.getViewportBorder() ).setBackground( StandaloneSoapUICore.SoapUITheme.BACKGROUND_COLOR );
140 }
141 catch( Exception e )
142 {
143 e.printStackTrace();
144 }
145
146 toggleLineNumbersMenuItem.setSelected( enable );
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 public RSyntaxTextArea getEditArea()
164 {
165 return editArea;
166 }
167
168 public void release()
169 {
170 if( model != null )
171 {
172 model.getSettings().removeSettingsListener( settingsListener );
173 }
174 model = null;
175 editArea.getDocument().removeDocumentListener( groovyDocumentListener );
176
177
178
179
180
181
182 }
183
184 public void selectError( String message )
185 {
186 int ix = message == null ? -1 : message.indexOf( "@ line " );
187 if( ix >= 0 )
188 {
189 try
190 {
191 int ix2 = message.indexOf( ',', ix );
192 int line = ix2 == -1 ? Integer.parseInt( message.substring( ix + 6 ).trim() ) : Integer.parseInt( message
193 .substring( ix + 6, ix2 ).trim() );
194 int column = 0;
195 if( ix2 != -1 )
196 {
197 ix = message.indexOf( "column ", ix2 );
198 if( ix >= 0 )
199 {
200 ix2 = message.indexOf( '.', ix );
201 column = ix2 == -1 ? Integer.parseInt( message.substring( ix + 7 ).trim() ) : Integer
202 .parseInt( message.substring( ix + 7, ix2 ).trim() );
203 }
204 }
205
206 editArea.setCaretPosition( editArea.getLineStartOffset( line - 1 ) + column - 1 );
207 }
208 catch( Exception ex )
209 {
210 }
211
212 editArea.requestFocus();
213 }
214 }
215
216 private KeywordMap initKeywords()
217 {
218 KeywordMap keywords = GroovyTokenMarker.getKeywords();
219
220 String[] kw = model.getKeywords();
221 if( kw != null )
222 {
223 for( String keyword : kw )
224 keywords.add( keyword, Token.KEYWORD2 );
225 }
226
227 return keywords;
228 }
229
230 private final class GroovyDocumentListener extends DocumentListenerAdapter
231 {
232 public void update( Document document )
233 {
234 GroovyEditor.this.model.setScript( editArea.getText() );
235 }
236 }
237
238 private final class InternalSettingsListener implements SettingsListener
239 {
240 public void settingChanged( String name, String newValue, String oldValue )
241 {
242 if( name.equals( UISettings.EDITOR_FONT ) )
243 {
244 Font newFont = Font.decode( newValue );
245 setEditorFont( newFont );
246 invalidate();
247 }
248 }
249 }
250
251 public void setEditorFont( Font newFont )
252 {
253 editArea.setFont( newFont );
254
255 for( SyntaxScheme scheme : editArea.getSyntaxHighlightingColorScheme().syntaxSchemes )
256 {
257 if( scheme != null )
258 {
259 scheme.font = newFont;
260 }
261 }
262 }
263
264 public void addCaretListener( CaretListener listener )
265 {
266 editArea.addCaretListener( listener );
267 }
268
269 public int getCaretPosition()
270 {
271 return editArea.getCaretPosition();
272 }
273
274 public int getLineOfOffset( int offset ) throws Exception
275 {
276 return editArea.getLineOfOffset( offset );
277 }
278
279 public int getLineStartOffset( int line ) throws Exception
280 {
281 return editArea.getLineStartOffset( line );
282 }
283
284 public void removeCaretListener( CaretListener listener )
285 {
286 editArea.removeCaretListener( listener );
287 }
288
289 private final class GoToLineAction extends AbstractAction
290 {
291 public GoToLineAction()
292 {
293 super( "Go To Line" );
294 putValue( Action.SHORT_DESCRIPTION, "Moves the caret to the specified line" );
295 putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu alt L" ) );
296 }
297
298 public void actionPerformed( ActionEvent e )
299 {
300 String line = UISupport.prompt( "Enter line-number to (1.." + ( editArea.getLineCount() ) + ")", "Go To Line",
301 String.valueOf( editArea.getCaretLineNumber() + 1 ) );
302
303 if( line != null )
304 {
305 try
306 {
307 int ln = Integer.parseInt( line ) - 1;
308 if( ln >= 0 && ln < editArea.getLineCount() )
309 {
310 editArea.scrollRectToVisible( editArea.modelToView( editArea.getLineStartOffset( ln ) ) );
311 editArea.setCaretPosition( getLineStartOffset( ln ) );
312 }
313 }
314 catch( Exception e1 )
315 {
316 }
317 }
318 }
319 }
320
321 private class RSyntaxTextAreaFindAndReplaceable implements FindAndReplaceable
322 {
323 public boolean isEditable()
324 {
325 return editArea.isEditable();
326 }
327
328 public int getCaretPosition()
329 {
330 return editArea.getCaretPosition();
331 }
332
333 public String getText()
334 {
335 return editArea.getText();
336 }
337
338 public void select( int start, int end )
339 {
340 editArea.select( start, end );
341 }
342
343 public int getSelectionStart()
344 {
345 return editArea.getSelectionStart();
346 }
347
348 public int getSelectionEnd()
349 {
350 return editArea.getSelectionEnd();
351 }
352
353 public void setSelectedText( String txt )
354 {
355 editArea.replaceSelection( txt );
356 }
357
358 public String getSelectedText()
359 {
360 return editArea.getSelectedText();
361 }
362 }
363 }