]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/javaeditor/JavaTemplatesPage.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / ui / org / eclipse / jdt / internal / ui / javaeditor / JavaTemplatesPage.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2011 Dakshinamurthy Karra, IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     Dakshinamurthy Karra (Jalian Systems) - Templates View - https://bugs.eclipse.org/bugs/show_bug.cgi?id=69581
10  *******************************************************************************/
11 package org.eclipse.jdt.internal.ui.javaeditor;
12
13 import org.eclipse.swt.SWT;
14 import org.eclipse.swt.graphics.Font;
15 import org.eclipse.swt.graphics.Image;
16 import org.eclipse.swt.layout.GridData;
17 import org.eclipse.swt.widgets.Composite;
18 import org.eclipse.swt.widgets.Control;
19
20 import org.eclipse.jface.preference.IPreferenceStore;
21 import org.eclipse.jface.resource.JFaceResources;
22 import org.eclipse.jface.window.Window;
23
24 import org.eclipse.jface.text.BadLocationException;
25 import org.eclipse.jface.text.Document;
26 import org.eclipse.jface.text.IDocument;
27 import org.eclipse.jface.text.ITextSelection;
28 import org.eclipse.jface.text.ITextViewerExtension;
29 import org.eclipse.jface.text.Position;
30 import org.eclipse.jface.text.Region;
31 import org.eclipse.jface.text.TextSelection;
32 import org.eclipse.jface.text.TextUtilities;
33 import org.eclipse.jface.text.source.ISourceViewer;
34 import org.eclipse.jface.text.source.SourceViewer;
35 import org.eclipse.jface.text.templates.ContextTypeRegistry;
36 import org.eclipse.jface.text.templates.DocumentTemplateContext;
37 import org.eclipse.jface.text.templates.Template;
38 import org.eclipse.jface.text.templates.TemplateContextType;
39 import org.eclipse.jface.text.templates.persistence.TemplateStore;
40
41 import org.eclipse.ui.texteditor.templates.AbstractTemplatesPage;
42
43 import org.eclipse.jdt.core.ICompilationUnit;
44
45 import org.eclipse.jdt.internal.corext.template.java.CompilationUnitContextType;
46 import org.eclipse.jdt.internal.corext.template.java.JavaContext;
47 import org.eclipse.jdt.internal.corext.template.java.JavaContextType;
48 import org.eclipse.jdt.internal.corext.template.java.JavaDocContext;
49 import org.eclipse.jdt.internal.corext.template.java.JavaDocContextType;
50 import org.eclipse.jdt.internal.corext.template.java.SWTContextType;
51
52 import org.eclipse.jdt.ui.PreferenceConstants;
53 import org.eclipse.jdt.ui.text.IJavaPartitions;
54 import org.eclipse.jdt.ui.text.JavaTextTools;
55
56 import org.eclipse.jdt.internal.ui.JavaPlugin;
57 import org.eclipse.jdt.internal.ui.JavaPluginImages;
58 import org.eclipse.jdt.internal.ui.preferences.EditTemplateDialog;
59 import org.eclipse.jdt.internal.ui.preferences.JavaSourcePreviewerUpdater;
60 import org.eclipse.jdt.internal.ui.text.SimpleJavaSourceViewerConfiguration;
61 import org.eclipse.jdt.internal.ui.text.template.contentassist.TemplateProposal;
62 import org.eclipse.jdt.internal.ui.text.template.preferences.TemplateVariableProcessor;
63
64
65 /**
66  * The templates page for the Java editor.
67  *
68  * @since 3.4
69  */
70 public class JavaTemplatesPage extends AbstractTemplatesPage {
71
72         private static final String PREFERENCE_PAGE_ID= "org.eclipse.jdt.ui.preferences.JavaTemplatePreferencePage"; //$NON-NLS-1$
73         private static final TemplateStore TEMPLATE_STORE= JavaPlugin.getDefault().getTemplateStore();
74         private static final IPreferenceStore PREFERENCE_STORE= JavaPlugin.getDefault().getPreferenceStore();
75         private static final ContextTypeRegistry TEMPLATE_CONTEXT_REGISTRY= JavaPlugin.getDefault().getTemplateContextRegistry();
76
77         private TemplateVariableProcessor fTemplateProcessor;
78         private JavaEditor fJavaEditor;
79
80         /**
81          * Create a new AbstractTemplatesPage for the JavaEditor
82          * 
83          * @param javaEditor the java editor
84          */
85         public JavaTemplatesPage(JavaEditor javaEditor) {
86                 super(javaEditor, javaEditor.getViewer());
87                 fJavaEditor= javaEditor;
88                 fTemplateProcessor= new TemplateVariableProcessor();
89         }
90
91         /*
92          * @see org.eclipse.ui.texteditor.templates.AbstractTemplatesPage#insertTemplate(org.eclipse.jface.text.templates.Template, org.eclipse.jface.text.IDocument)
93          */
94         @Override
95         protected void insertTemplate(Template template, IDocument document) {
96                 if (!fJavaEditor.validateEditorInputState())
97                         return;
98
99                 ISourceViewer contextViewer= fJavaEditor.getViewer();
100                 ITextSelection textSelection= (ITextSelection) contextViewer.getSelectionProvider().getSelection();
101                 if (!isValidTemplate(document, template, textSelection.getOffset(), textSelection.getLength()))
102                         return;
103                 beginCompoundChange(contextViewer);
104                 /*
105                  * The Editor checks whether a completion for a word exists before it allows for the template to be
106                  * applied. We pickup the current text at the selection position and replace it with the first char
107                  * of the template name for this to succeed.
108                  * Another advantage by this method is that the template replaces the selected text provided the
109                  * selection by itself is not used in the template pattern.
110                  */
111                 String savedText;
112                 try {
113                         savedText= document.get(textSelection.getOffset(), textSelection.getLength());
114                         if (savedText.length() == 0) {
115                                 String prefix= getIdentifierPart(document, template, textSelection.getOffset(), textSelection.getLength());
116                                 if (prefix.length() > 0 && !template.getName().startsWith(prefix.toString())) {
117                                         return;
118                                 }
119                                 if (prefix.length() > 0) {
120                                         contextViewer.setSelectedRange(textSelection.getOffset() - prefix.length(), prefix.length());
121                                         textSelection= (ITextSelection) contextViewer.getSelectionProvider().getSelection();
122                                 }
123                         }
124                         document.replace(textSelection.getOffset(), textSelection.getLength(), template.getName().substring(0, 1));
125                 } catch (BadLocationException e) {
126                         endCompoundChange(contextViewer);
127                         return;
128                 }
129                 Position position= new Position(textSelection.getOffset() + 1, 0);
130                 Region region= new Region(textSelection.getOffset() + 1, 0);
131                 contextViewer.getSelectionProvider().setSelection(new TextSelection(textSelection.getOffset(), 1));
132                 ICompilationUnit compilationUnit= (ICompilationUnit) EditorUtility.getEditorInputJavaElement(fJavaEditor, true);
133
134                 TemplateContextType type= getContextTypeRegistry().getContextType(template.getContextTypeId());
135                 DocumentTemplateContext context= ((CompilationUnitContextType) type).createContext(document, position, compilationUnit);
136                 context.setVariable("selection", savedText); //$NON-NLS-1$
137                 if (context.getKey().length() == 0) {
138                         try {
139                                 document.replace(textSelection.getOffset(), 1, savedText);
140                         } catch (BadLocationException e) {
141                                 endCompoundChange(contextViewer);
142                                 return;
143                         }
144                 }
145                 TemplateProposal proposal= new TemplateProposal(template, context, region, null);
146                 fJavaEditor.getSite().getPage().activate(fJavaEditor);
147                 proposal.apply(fJavaEditor.getViewer(), ' ', 0, region.getOffset());
148                 endCompoundChange(contextViewer);
149         }
150
151         /* (non-Javadoc)
152          * @see org.eclipse.ui.texteditor.templates.AbstractTemplatesPage#getContextTypeRegistry()
153          */
154         @Override
155         protected ContextTypeRegistry getContextTypeRegistry() {
156                 return TEMPLATE_CONTEXT_REGISTRY;
157         }
158
159         /* (non-Javadoc)
160          * @see org.eclipse.ui.texteditor.templates.AbstractTemplatesPage#getTemplatePreferenceStore()
161          */
162         @Override
163         protected IPreferenceStore getTemplatePreferenceStore() {
164                 return PREFERENCE_STORE;
165         }
166
167         /* (non-Javadoc)
168          * @see org.eclipse.ui.texteditor.templates.AbstractTemplatesPage#getTemplateStore()
169          */
170         @Override
171         public TemplateStore getTemplateStore() {
172                 return TEMPLATE_STORE;
173         }
174
175         /*
176          * @see org.eclipse.ui.texteditor.templates.TextEditorTemplatesPage#isValidTemplate(org.eclipse.jface.text.templates.Template, int, int)
177          */
178         @Override
179         protected boolean isValidTemplate(IDocument document, Template template, int offset, int length) {
180                 String[] contextIds= getContextTypeIds(document, offset);
181                 for (int i= 0; i < contextIds.length; i++) {
182                         if (contextIds[i].equals(template.getContextTypeId())) {
183                                 DocumentTemplateContext context= getContext(document, template, offset, length);
184                                 return context.canEvaluate(template) || isTemplateAllowed(context, template);
185                         }
186                 }
187                 return false;
188         }
189
190         /* (non-Javadoc)
191          * @see org.eclipse.ui.texteditor.templates.TextEditorTemplatesPage#createPatternViewer(org.eclipse.swt.widgets.Composite)
192          */
193         @Override
194         protected SourceViewer createPatternViewer(Composite parent) {
195                 IDocument document= new Document();
196                 JavaTextTools tools= JavaPlugin.getDefault().getJavaTextTools();
197                 tools.setupJavaDocumentPartitioner(document, IJavaPartitions.JAVA_PARTITIONING);
198                 IPreferenceStore store= JavaPlugin.getDefault().getCombinedPreferenceStore();
199                 JavaSourceViewer viewer= new JavaSourceViewer(parent, null, null, false, SWT.V_SCROLL | SWT.H_SCROLL, store);
200                 SimpleJavaSourceViewerConfiguration configuration= new SimpleJavaSourceViewerConfiguration(tools.getColorManager(), store, null, IJavaPartitions.JAVA_PARTITIONING, false);
201                 viewer.configure(configuration);
202                 viewer.setEditable(false);
203                 viewer.setDocument(document);
204
205                 Font font= JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT);
206                 viewer.getTextWidget().setFont(font);
207                 new JavaSourcePreviewerUpdater(viewer, configuration, store);
208
209                 Control control= viewer.getControl();
210                 GridData data= new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_VERTICAL);
211                 control.setLayoutData(data);
212
213                 viewer.setEditable(false);
214                 return viewer;
215         }
216
217         /* (non-Javadoc)
218          * @see org.eclipse.ui.texteditor.templates.AbstractTemplatesPage#getImageForTemplate(org.eclipse.jface.text.templates.Template)
219          */
220         @Override
221         protected Image getImage(Template template) {
222                 String contextId= template.getContextTypeId();
223                 if (SWTContextType.ID_ALL.equals(contextId) || SWTContextType.ID_STATEMENTS.equals(contextId) || SWTContextType.ID_MEMBERS.equals(contextId))
224                         return JavaPluginImages.get(JavaPluginImages.IMG_OBJS_SWT_TEMPLATE);
225                 return JavaPluginImages.get(JavaPluginImages.IMG_OBJS_TEMPLATE);
226         }
227
228         /*
229          * @see org.eclipse.ui.texteditor.templates.TextEditorTemplatesPage#editTemplate(org.eclipse.jface.text.templates.Template, boolean, boolean)
230          */
231         @Override
232         protected Template editTemplate(Template template, boolean edit, boolean isNameModifiable) {
233                 EditTemplateDialog dialog= new EditTemplateDialog(getSite().getShell(), template, edit, isNameModifiable, getContextTypeRegistry());
234                 if (dialog.open() == Window.OK)
235                         return dialog.getTemplate();
236                 return null;
237         }
238
239         /*
240          * @see org.eclipse.ui.texteditor.templates.TextEditorTemplatesPage#updatePatternViewer(org.eclipse.jface.text.templates.Template)
241          */
242         @Override
243         protected void updatePatternViewer(Template template) {
244                 if (template == null) {
245                         getPatternViewer().getDocument().set(""); //$NON-NLS-1$
246                         return ;
247                 }
248                 String contextId= template.getContextTypeId();
249                 TemplateContextType type= getContextTypeRegistry().getContextType(contextId);
250                 fTemplateProcessor.setContextType(type);
251
252                 IDocument doc= getPatternViewer().getDocument();
253
254                 String start= null;
255                 if ("javadoc".equals(contextId)) { //$NON-NLS-1$
256                         start= "/**" + doc.getLegalLineDelimiters()[0]; //$NON-NLS-1$
257                 } else
258                         start= ""; //$NON-NLS-1$
259
260                 doc.set(start + template.getPattern());
261                 int startLen= start.length();
262                 getPatternViewer().setDocument(doc, startLen, doc.getLength() - startLen);
263         }
264
265         /* (non-Javadoc)
266          * @see org.eclipse.ui.texteditor.templates.AbstractTemplatesPage#getPreferencePageId()
267          */
268         @Override
269         protected String getPreferencePageId() {
270                 return PREFERENCE_PAGE_ID;
271         }
272
273         /**
274          * Undomanager - end compound change
275          * 
276          * @param viewer the viewer
277          */
278         private void endCompoundChange(ISourceViewer viewer) {
279                 if (viewer instanceof ITextViewerExtension)
280                         ((ITextViewerExtension) viewer).getRewriteTarget().endCompoundChange();
281         }
282
283         /**
284          * Undomanager - begin a compound change
285          * 
286          * @param viewer the viewer
287          */
288         private void beginCompoundChange(ISourceViewer viewer) {
289                 if (viewer instanceof ITextViewerExtension)
290                         ((ITextViewerExtension) viewer).getRewriteTarget().beginCompoundChange();
291         }
292
293         /**
294          * Check whether the template is allowed eventhough the context can't evaluate it. This is
295          * needed because the Dropping of a template is more lenient than ctl-space invoked code assist.
296          * 
297          * @param context the template context
298          * @param template the template
299          * @return true if the template is allowed
300          */
301         private boolean isTemplateAllowed(DocumentTemplateContext context, Template template) {
302                 int offset;
303                 try {
304                         if (template.getContextTypeId().equals(JavaDocContextType.ID)) {
305                                 return (offset= context.getCompletionOffset()) > 0 && Character.isWhitespace(context.getDocument().getChar(offset - 1));
306                         } else {
307                                 return ((offset= context.getCompletionOffset()) > 0 && !isTemplateNamePart(context.getDocument().getChar(offset - 1)));
308                         }
309                 } catch (BadLocationException e) {
310                 }
311                 return false;
312         }
313
314         /**
315          * Checks whether the character is a valid character in Java template names
316          * 
317          * @param ch the character
318          * @return <code>true</code> if the character is part of a template name
319          */
320         private boolean isTemplateNamePart(char ch) {
321                 return !Character.isWhitespace(ch) && ch != '(' && ch != ')' && ch != '{' && ch != '}' && ch != ';';
322         }
323
324         /**
325          * Get context
326          * 
327          * @param document the document
328          * @param template the template
329          * @param offset the offset
330          * @param length the length
331          * @return the context
332          */
333         private DocumentTemplateContext getContext(IDocument document, Template template, final int offset, int length) {
334                 DocumentTemplateContext context;
335                 if (template.getContextTypeId().equals(JavaDocContextType.ID)) {
336                         context= new JavaDocContext(getContextTypeRegistry().getContextType(template.getContextTypeId()), document, new Position(offset, length), (ICompilationUnit) EditorUtility
337                                         .getEditorInputJavaElement(fJavaEditor, true));
338                 } else {
339                         context= new JavaContext(getContextTypeRegistry().getContextType(template.getContextTypeId()), document, new Position(offset, length), (ICompilationUnit) EditorUtility.getEditorInputJavaElement(
340                                         fJavaEditor, true));
341                 }
342                 return context;
343         }
344
345         /**
346          * Get the active contexts for the given position in the document.
347          * <p>
348          * FIXME: should trigger code assist to get the context.
349          * </p>
350          * 
351          * @param document the document
352          * @param offset the offset
353          * @return an array of valid context id
354          */
355         @Override
356         protected String[] getContextTypeIds(IDocument document, int offset) {
357                 try {
358                         String partition= TextUtilities.getContentType(document, IJavaPartitions.JAVA_PARTITIONING, offset, true);
359                         String[] ids= new String[] { JavaContextType.ID_ALL, JavaContextType.ID_MEMBERS, JavaContextType.ID_STATEMENTS, SWTContextType.ID_ALL, SWTContextType.ID_STATEMENTS, SWTContextType.ID_MEMBERS};
360                         if (partition.equals(IJavaPartitions.JAVA_DOC))
361                                 ids= new String[] { JavaDocContextType.ID };
362                         return ids;
363                 } catch (BadLocationException e) {
364                         return new String[0];
365                 }
366         }
367
368         /**
369          * Get the Java identifier terminated at the given offset
370          * 
371          * @param document the document
372          * @param template the template
373          * @param offset the offset
374          * @param length the length
375          * @return the identifier part the Java identifier
376          */
377         private String getIdentifierPart(IDocument document, Template template, int offset, int length) {
378                 return getContext(document, template, offset, length).getKey();
379         }
380 }