|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 package com.nokia.testfw.stf.scripteditor.editors; |
|
19 |
|
20 import java.util.ArrayList; |
|
21 import java.util.HashMap; |
|
22 import java.util.ResourceBundle; |
|
23 import java.util.regex.Matcher; |
|
24 import java.util.regex.Pattern; |
|
25 |
|
26 import org.eclipse.core.resources.IFile; |
|
27 import org.eclipse.core.resources.IResource; |
|
28 import org.eclipse.core.resources.ResourcesPlugin; |
|
29 import org.eclipse.core.runtime.IConfigurationElement; |
|
30 import org.eclipse.core.runtime.IProgressMonitor; |
|
31 import org.eclipse.jface.action.Action; |
|
32 import org.eclipse.jface.text.IDocument; |
|
33 import org.eclipse.jface.text.Position; |
|
34 import org.eclipse.jface.text.source.IAnnotationModelExtension; |
|
35 import org.eclipse.jface.text.source.ISourceViewer; |
|
36 import org.eclipse.jface.text.source.IVerticalRuler; |
|
37 import org.eclipse.jface.text.source.projection.ProjectionAnnotation; |
|
38 import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel; |
|
39 import org.eclipse.jface.text.source.projection.ProjectionSupport; |
|
40 import org.eclipse.jface.text.source.projection.ProjectionViewer; |
|
41 import org.eclipse.jface.viewers.ISelectionChangedListener; |
|
42 import org.eclipse.jface.viewers.ITreeSelection; |
|
43 import org.eclipse.jface.viewers.SelectionChangedEvent; |
|
44 import org.eclipse.jface.viewers.TreePath; |
|
45 import org.eclipse.jface.viewers.TreeViewer; |
|
46 import org.eclipse.swt.events.KeyEvent; |
|
47 import org.eclipse.swt.events.KeyListener; |
|
48 import org.eclipse.swt.events.SelectionEvent; |
|
49 import org.eclipse.swt.events.SelectionListener; |
|
50 import org.eclipse.swt.layout.GridData; |
|
51 import org.eclipse.swt.layout.GridLayout; |
|
52 import org.eclipse.swt.widgets.Composite; |
|
53 import org.eclipse.swt.widgets.Control; |
|
54 import org.eclipse.swt.widgets.MessageBox; |
|
55 import org.eclipse.swt.widgets.Tree; |
|
56 import org.eclipse.swt.widgets.TreeItem; |
|
57 import org.eclipse.ui.IEditorInput; |
|
58 import org.eclipse.ui.PlatformUI; |
|
59 import org.eclipse.ui.editors.text.TextEditor; |
|
60 import org.eclipse.ui.texteditor.ContentAssistAction; |
|
61 import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; |
|
62 import org.eclipse.ui.views.contentoutline.IContentOutlinePage; |
|
63 |
|
64 import com.nokia.testfw.stf.scripteditor.utils.ScriptParser; |
|
65 import com.nokia.testfw.stf.scripteditor.utils.Section; |
|
66 import com.nokia.testfw.stf.scripteditor.utils.SectionFinder; |
|
67 import com.nokia.testfw.stf.scripteditor.utils.TestCase; |
|
68 |
|
69 /** |
|
70 * STIF script file editor. |
|
71 * |
|
72 */ |
|
73 |
|
74 public class ScriptEditor extends TextEditor implements |
|
75 ISelectionChangedListener, SelectionListener { |
|
76 |
|
77 private ScriptEditorOutlinePage outlinePage; |
|
78 |
|
79 private ProjectionAnnotationModel annotationModel; |
|
80 |
|
81 private ArrayList<ProjectionAnnotation> currentAnnotations = new ArrayList<ProjectionAnnotation>(); |
|
82 |
|
83 private ScriptEditorConfiguration configuration; |
|
84 |
|
85 private ScriptParser parser; |
|
86 |
|
87 public ScriptEditor() { |
|
88 configuration = new ScriptEditorConfiguration(); |
|
89 configuration.changeConfigurationMode(null); |
|
90 setSourceViewerConfiguration(configuration); |
|
91 parser = new ScriptParser(); |
|
92 } |
|
93 |
|
94 /** |
|
95 * Saves the editor document |
|
96 */ |
|
97 public void doSave(IProgressMonitor monitor) { |
|
98 refreshOutlineFoldingAndParse(); |
|
99 super.doSave(monitor); |
|
100 } |
|
101 |
|
102 /** |
|
103 * Checks editor content syntax and updates folding. |
|
104 */ |
|
105 public void refreshOutlineFoldingAndParse() { |
|
106 if (outlinePage != null) { |
|
107 TestCase[] testCases = (TestCase[]) (SectionFinder.getSections(this |
|
108 .getDocumentProvider().getDocument(getEditorInput()))); |
|
109 outlinePage.updateViewWithTests(testCases); |
|
110 updateFoldingStructure(testCases); |
|
111 } |
|
112 checkScript(); |
|
113 } |
|
114 |
|
115 /** |
|
116 * Checks editor content syntax. |
|
117 */ |
|
118 private void checkScript() { |
|
119 String scriptContent = getDocumentProvider().getDocument( |
|
120 getEditorInput()).get(); |
|
121 parser.checkScripterScript(scriptContent, getEditorInput()); |
|
122 configuration.changeConfigurationMode(parser.subSectionContent); |
|
123 } |
|
124 |
|
125 /* |
|
126 * (non-Javadoc) |
|
127 * |
|
128 * Method declared on SelectionListener |
|
129 */ |
|
130 public void widgetSelected(SelectionEvent selectionEv) { |
|
131 String scriptContent = getDocumentProvider().getDocument( |
|
132 getEditorInput()).get(); |
|
133 try { |
|
134 |
|
135 ScriptEditorConfiguration conf = (ScriptEditorConfiguration) getSourceViewerConfiguration(); |
|
136 conf.changeConfigurationMode(null); |
|
137 parser.checkScripterScript(scriptContent, getEditorInput()); |
|
138 |
|
139 this.getSourceViewer().invalidateTextPresentation(); |
|
140 |
|
141 } catch(Exception ex) { |
|
142 MessageBox message = new MessageBox(PlatformUI |
|
143 .getWorkbench().getActiveWorkbenchWindow().getShell()); |
|
144 message.setText("Problems while saving editor mode"); |
|
145 message.setMessage(ex.getMessage()); |
|
146 } |
|
147 } |
|
148 |
|
149 /* |
|
150 * (non-Javadoc) Method declared on SelectionListener |
|
151 */ |
|
152 public void widgetDefaultSelected(SelectionEvent arg0) { |
|
153 |
|
154 } |
|
155 |
|
156 /* |
|
157 * (non-Javadoc) |
|
158 * |
|
159 * @see IStorage#getAdapter() |
|
160 */ |
|
161 public Object getAdapter(Class required) { |
|
162 if (IContentOutlinePage.class.equals(required)) { |
|
163 if (outlinePage == null) { |
|
164 outlinePage = new ScriptEditorOutlinePage(this); |
|
165 } |
|
166 return outlinePage; |
|
167 } |
|
168 return super.getAdapter(required); |
|
169 } |
|
170 |
|
171 /* |
|
172 * (non-Javadoc) |
|
173 * |
|
174 * @see |
|
175 * org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action |
|
176 * .IAction, org.eclipse.jface.viewers.ISelection) |
|
177 */ |
|
178 public void selectionChanged(SelectionChangedEvent sce) { |
|
179 ITreeSelection selection = (ITreeSelection) sce.getSelection(); |
|
180 if (selection.isEmpty()) |
|
181 return; |
|
182 |
|
183 TreePath[] selections = selection.getPaths(); |
|
184 TestCase testCase = (TestCase) selections[0].getFirstSegment(); |
|
185 |
|
186 IDocument doc = getDocumentProvider().getDocument(getEditorInput()); |
|
187 |
|
188 String contentOfDoc = doc.get(); |
|
189 String name = testCase.getName(); |
|
190 name = name.replaceAll("\\(", "\\\\(").replaceAll("\\)", "\\\\)"); |
|
191 String patternString = "\\s+title\\s+(" + name + ")\\s*$"; |
|
192 |
|
193 Pattern pattern = Pattern.compile(patternString, Pattern.MULTILINE); |
|
194 Matcher regExMatcher = pattern.matcher(contentOfDoc); |
|
195 ArrayList<Integer> indexesList = new ArrayList<Integer>(); |
|
196 while (regExMatcher.find()) { |
|
197 indexesList.add(regExMatcher.start(1)); |
|
198 indexesList.add(regExMatcher.end(1)); |
|
199 } |
|
200 |
|
201 int oneFromCasesWithSameName = 0; |
|
202 if (indexesList.size() > 2) { |
|
203 TreeViewer tv = (TreeViewer) sce.getSource(); |
|
204 Tree tree = tv.getTree(); |
|
205 TreeItem[] treeItems = tree.getItems(); |
|
206 |
|
207 for (int i = 0; i < treeItems.length; i++) { |
|
208 if (treeItems[i].getText().equals( |
|
209 tree.getSelection()[0].getText())) { |
|
210 if (treeItems[i] == tree.getSelection()[0]) { |
|
211 break; |
|
212 } |
|
213 oneFromCasesWithSameName++; |
|
214 } |
|
215 } |
|
216 } |
|
217 if (indexesList.size() > 0) { |
|
218 selectAndReveal(indexesList.get(oneFromCasesWithSameName * 2), |
|
219 indexesList.get(oneFromCasesWithSameName * 2 + 1) |
|
220 - indexesList.get(oneFromCasesWithSameName * 2)); |
|
221 } |
|
222 } |
|
223 |
|
224 /** |
|
225 * Updates folding structure of the current file. Invalid annotations are |
|
226 * removed and new ones are added |
|
227 */ |
|
228 public void updateFoldingStructure(Section[] sections) { |
|
229 HashMap<ProjectionAnnotation, Position> newAnnotations = new HashMap<ProjectionAnnotation, Position>(); |
|
230 ArrayList<ProjectionAnnotation> annotationsToRemove = new ArrayList<ProjectionAnnotation>(); |
|
231 |
|
232 for (int i = 0; i < currentAnnotations.size(); i++) { |
|
233 boolean annotationExists = false; |
|
234 for (int j = 0; j < sections.length; j++) { |
|
235 if (currentAnnotations.get(i).getText().equals( |
|
236 sections[j].getName())) { |
|
237 annotationExists = true; |
|
238 break; |
|
239 } |
|
240 } |
|
241 if (!annotationExists) { |
|
242 annotationsToRemove.add(currentAnnotations.get(i)); |
|
243 currentAnnotations.remove(i); |
|
244 } |
|
245 } |
|
246 |
|
247 for (int i = 0; i < sections.length; i++) { |
|
248 if (sections[i].getIsNew()) { |
|
249 ProjectionAnnotation annotation = new ProjectionAnnotation(); |
|
250 annotation.setText(sections[i].getName()); |
|
251 int length = sections[i].getEndOffset() |
|
252 - sections[i].getStartOffset(); |
|
253 newAnnotations.put(annotation, new Position(sections[i] |
|
254 .getStartOffset(), length)); |
|
255 currentAnnotations.add(annotation); |
|
256 } |
|
257 } |
|
258 |
|
259 IAnnotationModelExtension modelExtension = (IAnnotationModelExtension) annotationModel; |
|
260 modelExtension.replaceAnnotations(annotationsToRemove |
|
261 .toArray(new ProjectionAnnotation[0]), newAnnotations); |
|
262 } |
|
263 |
|
264 /* |
|
265 * (non-Javadoc) |
|
266 * |
|
267 * Overriden |
|
268 */ |
|
269 public void createPartControl(Composite arg0) { |
|
270 super.createPartControl(arg0); |
|
271 |
|
272 ProjectionViewer viewer = (ProjectionViewer) getSourceViewer(); |
|
273 ProjectionSupport support = new ProjectionSupport(viewer, |
|
274 getAnnotationAccess(), getSharedColors()); |
|
275 support.install(); |
|
276 |
|
277 viewer.doOperation(ProjectionViewer.TOGGLE); |
|
278 |
|
279 annotationModel = viewer.getProjectionAnnotationModel(); |
|
280 |
|
281 Control control = (Control) getAdapter(org.eclipse.swt.widgets.Control.class); |
|
282 |
|
283 control.addKeyListener(new KeyListener() { |
|
284 public void keyPressed(KeyEvent e) { |
|
285 refreshOutlineFoldingAndParse(); // method responsible for |
|
286 // refreshing and parsing |
|
287 // tests invoked after any |
|
288 // key event. |
|
289 } |
|
290 |
|
291 public void keyReleased(KeyEvent e) { |
|
292 } |
|
293 }); |
|
294 |
|
295 } |
|
296 |
|
297 /* |
|
298 * (non-Javadoc) |
|
299 * |
|
300 * Overriden |
|
301 */ |
|
302 protected ISourceViewer createSourceViewer(Composite parent, |
|
303 IVerticalRuler ruler, int styles) { |
|
304 |
|
305 GridLayout layout = new GridLayout(); |
|
306 layout.numColumns = 1; |
|
307 layout.marginTop = 0; |
|
308 layout.marginBottom = 0; |
|
309 layout.marginLeft = 0; |
|
310 layout.marginRight = 0; |
|
311 parent.setLayout(layout); |
|
312 |
|
313 GridData scriptEditorGridData = new GridData(GridData.FILL_HORIZONTAL |
|
314 | GridData.FILL_VERTICAL); |
|
315 |
|
316 ProjectionViewer sourceViewer = new ProjectionViewer(parent, ruler, |
|
317 getOverviewRuler(), isOverviewRulerVisible(), styles); |
|
318 getSourceViewerDecorationSupport(sourceViewer); |
|
319 |
|
320 sourceViewer.getTextWidget().getParent().setLayoutData( |
|
321 scriptEditorGridData); |
|
322 |
|
323 return sourceViewer; |
|
324 } |
|
325 |
|
326 /* |
|
327 * (non-Javadoc) |
|
328 * |
|
329 * @see org.eclipse.ui.editors.text.TextEditor#createActions() |
|
330 */ |
|
331 protected void createActions() { |
|
332 super.createActions(); |
|
333 ResourceBundle resourceBundle = ResourceBundle |
|
334 .getBundle("STIFScriptsEditor"); |
|
335 Action action = new ContentAssistAction(resourceBundle, |
|
336 "ContentAssistProposal.", this); |
|
337 String id = ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS; |
|
338 action.setActionDefinitionId(id); |
|
339 setAction("ContentAssistProposal", action); |
|
340 markAsStateDependentAction("ContentAssistProposal", true); |
|
341 checkScript(); |
|
342 |
|
343 // action = new TextOperationAction(resourceBundle, "Comment.", this, |
|
344 // ITextOperationTarget.PREFIX); |
|
345 // |
|
346 // action.setActionDefinitionId("org.eclipse.cdt.ui.edit.text.c.add.block.comment"); |
|
347 // |
|
348 // setAction("Comment", action); |
|
349 // |
|
350 // markAsStateDependentAction("Comment", true); |
|
351 // |
|
352 // |
|
353 // action = new TextOperationAction(resourceBundle, |
|
354 // "Uncomment.", this, |
|
355 // ITextOperationTarget.STRIP_PREFIX); |
|
356 // |
|
357 // action.setActionDefinitionId("org.eclipse.cdt.ui.edit.text.c.add.block.uncomment"); |
|
358 // setAction("Uncomment", action); |
|
359 // markAsStateDependentAction("Uncomment", true); |
|
360 // |
|
361 // action = new ToggleCommentAction(resourceBundle, "ToggleComment.", |
|
362 // this); |
|
363 // action.setActionDefinitionId("org.eclipse.cdt.ui.edit.text.c.toggle.comment"); |
|
364 // setAction("ToggleComment", action); |
|
365 // markAsStateDependentAction("ToggleComment", true); |
|
366 // |
|
367 // ISourceViewer sourceViewer = getSourceViewer(); |
|
368 // SourceViewerConfiguration configuration = |
|
369 // getSourceViewerConfiguration(); |
|
370 // ((ToggleCommentAction) action).configure(sourceViewer, |
|
371 // configuration); |
|
372 |
|
373 } |
|
374 |
|
375 /** |
|
376 * Gets resource associated with editor input |
|
377 * |
|
378 * @return resource |
|
379 */ |
|
380 protected IResource getResource() { |
|
381 IEditorInput input = getEditorInput(); |
|
382 if (input == null) { |
|
383 return null; |
|
384 } |
|
385 IResource resource = (IResource) input.getAdapter(IFile.class); |
|
386 if (resource == null) { |
|
387 resource = (IResource) input.getAdapter(IResource.class); |
|
388 if (resource == null) { |
|
389 resource = ResourcesPlugin.getWorkspace().getRoot(); |
|
390 |
|
391 } |
|
392 } |
|
393 refreshOutlineFoldingAndParse(); |
|
394 return resource; |
|
395 } |
|
396 |
|
397 public ScriptEditorConfiguration getConfiguration() { |
|
398 return configuration; |
|
399 } |
|
400 |
|
401 public void setInitializationData(IConfigurationElement cfig, |
|
402 String propertyName, Object data) { |
|
403 super.setInitializationData(cfig, propertyName, data); |
|
404 } |
|
405 |
|
406 /** |
|
407 * override the method to always display line number |
|
408 */ |
|
409 protected boolean isLineNumberRulerVisible() { |
|
410 return true; |
|
411 } |
|
412 |
|
413 } |