KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > text > templates > TemplateProposal


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jface.text.templates;
12
13 import org.eclipse.swt.graphics.Image;
14 import org.eclipse.swt.graphics.Point;
15 import org.eclipse.swt.widgets.Shell;
16
17 import org.eclipse.core.runtime.Assert;
18
19 import org.eclipse.jface.dialogs.MessageDialog;
20
21 import org.eclipse.jface.text.BadLocationException;
22 import org.eclipse.jface.text.BadPositionCategoryException;
23 import org.eclipse.jface.text.DocumentEvent;
24 import org.eclipse.jface.text.IDocument;
25 import org.eclipse.jface.text.IInformationControlCreator;
26 import org.eclipse.jface.text.IRegion;
27 import org.eclipse.jface.text.ITextViewer;
28 import org.eclipse.jface.text.Position;
29 import org.eclipse.jface.text.Region;
30 import org.eclipse.jface.text.contentassist.ICompletionProposal;
31 import org.eclipse.jface.text.contentassist.ICompletionProposalExtension;
32 import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
33 import org.eclipse.jface.text.contentassist.ICompletionProposalExtension3;
34 import org.eclipse.jface.text.contentassist.IContextInformation;
35 import org.eclipse.jface.text.link.ILinkedModeListener;
36 import org.eclipse.jface.text.link.LinkedModeModel;
37 import org.eclipse.jface.text.link.LinkedModeUI;
38 import org.eclipse.jface.text.link.LinkedPosition;
39 import org.eclipse.jface.text.link.LinkedPositionGroup;
40 import org.eclipse.jface.text.link.ProposalPosition;
41
42
43 /**
44  * A template completion proposal.
45  * <p>
46  * Clients may subclass.</p>
47  *
48  * @since 3.0
49  */

50 public class TemplateProposal implements ICompletionProposal, ICompletionProposalExtension, ICompletionProposalExtension2, ICompletionProposalExtension3 {
51
52     private final Template fTemplate;
53     private final TemplateContext fContext;
54     private final Image fImage;
55     private final IRegion fRegion;
56     private int fRelevance;
57
58     private IRegion fSelectedRegion; // initialized by apply()
59
private String JavaDoc fDisplayString;
60     private InclusivePositionUpdater fUpdater;
61     private IInformationControlCreator fInformationControlCreator;
62
63     /**
64      * Creates a template proposal with a template and its context.
65      *
66      * @param template the template
67      * @param context the context in which the template was requested.
68      * @param region the region this proposal is applied to
69      * @param image the icon of the proposal.
70      */

71     public TemplateProposal(Template template, TemplateContext context, IRegion region, Image image) {
72         this(template, context, region, image, 0);
73     }
74
75     /**
76      * Creates a template proposal with a template and its context.
77      *
78      * @param template the template
79      * @param context the context in which the template was requested.
80      * @param image the icon of the proposal.
81      * @param region the region this proposal is applied to
82      * @param relevance the relevance of the proposal
83      */

84     public TemplateProposal(Template template, TemplateContext context, IRegion region, Image image, int relevance) {
85         Assert.isNotNull(template);
86         Assert.isNotNull(context);
87         Assert.isNotNull(region);
88
89         fTemplate= template;
90         fContext= context;
91         fImage= image;
92         fRegion= region;
93
94         fDisplayString= null;
95
96         fRelevance= relevance;
97     }
98
99     /**
100      * Sets the information control creator for this completion proposal.
101      *
102      * @param informationControlCreator the information control creator
103      * @since 3.1
104      */

105     public final void setInformationControlCreator(IInformationControlCreator informationControlCreator) {
106         fInformationControlCreator= informationControlCreator;
107     }
108
109     /**
110      * Returns the template of this proposal.
111      *
112      * @return the template of this proposal
113      * @since 3.1
114      */

115     protected final Template getTemplate() {
116         return fTemplate;
117     }
118
119     /**
120      * Returns the context in which the template was requested.
121      *
122      * @return the context in which the template was requested
123      * @since 3.1
124      */

125     protected final TemplateContext getContext() {
126         return fContext;
127     }
128
129     /*
130      * @see ICompletionProposal#apply(IDocument)
131      */

132     public final void apply(IDocument document) {
133         // not called anymore
134
}
135
136     /**
137      * Inserts the template offered by this proposal into the viewer's document
138      * and sets up a <code>LinkedModeUI</code> on the viewer to edit any of
139      * the template's unresolved variables.
140      *
141      * @param viewer {@inheritDoc}
142      * @param trigger {@inheritDoc}
143      * @param stateMask {@inheritDoc}
144      * @param offset {@inheritDoc}
145      */

146     public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
147
148         IDocument document= viewer.getDocument();
149         try {
150             fContext.setReadOnly(false);
151             TemplateBuffer templateBuffer;
152             try {
153                 templateBuffer= fContext.evaluate(fTemplate);
154             } catch (TemplateException e1) {
155                 fSelectedRegion= fRegion;
156                 return;
157             }
158
159             int start= getReplaceOffset();
160             int end= Math.max(getReplaceEndOffset(), offset);
161
162             // insert template string
163
String JavaDoc templateString= templateBuffer.getString();
164             document.replace(start, end - start, templateString);
165
166
167             // translate positions
168
LinkedModeModel model= new LinkedModeModel();
169             TemplateVariable[] variables= templateBuffer.getVariables();
170             boolean hasPositions= false;
171             for (int i= 0; i != variables.length; i++) {
172                 TemplateVariable variable= variables[i];
173
174                 if (variable.isUnambiguous())
175                     continue;
176
177                 LinkedPositionGroup group= new LinkedPositionGroup();
178
179                 int[] offsets= variable.getOffsets();
180                 int length= variable.getLength();
181
182                 String JavaDoc[] values= variable.getValues();
183                 ICompletionProposal[] proposals= new ICompletionProposal[values.length];
184                 for (int j= 0; j < values.length; j++) {
185                     ensurePositionCategoryInstalled(document, model);
186                     Position pos= new Position(offsets[0] + start, length);
187                     document.addPosition(getCategory(), pos);
188                     proposals[j]= new PositionBasedCompletionProposal(values[j], pos, length);
189                 }
190
191                 for (int j= 0; j != offsets.length; j++)
192                     if (j == 0 && proposals.length > 1)
193                         group.addPosition(new ProposalPosition(document, offsets[j] + start, length, proposals));
194                     else
195                         group.addPosition(new LinkedPosition(document, offsets[j] + start, length));
196
197                 model.addGroup(group);
198                 hasPositions= true;
199             }
200
201             if (hasPositions) {
202                 model.forceInstall();
203                 LinkedModeUI ui= new LinkedModeUI(model, viewer);
204                 ui.setExitPosition(viewer, getCaretOffset(templateBuffer) + start, 0, Integer.MAX_VALUE);
205                 ui.enter();
206
207                 fSelectedRegion= ui.getSelectedRegion();
208             } else {
209                 ensurePositionCategoryRemoved(document);
210                 fSelectedRegion= new Region(getCaretOffset(templateBuffer) + start, 0);
211             }
212
213         } catch (BadLocationException e) {
214             openErrorDialog(viewer.getTextWidget().getShell(), e);
215             ensurePositionCategoryRemoved(document);
216             fSelectedRegion= fRegion;
217         } catch (BadPositionCategoryException e) {
218             openErrorDialog(viewer.getTextWidget().getShell(), e);
219             fSelectedRegion= fRegion;
220         }
221
222     }
223
224     private void ensurePositionCategoryInstalled(final IDocument document, LinkedModeModel model) {
225         if (!document.containsPositionCategory(getCategory())) {
226             document.addPositionCategory(getCategory());
227             fUpdater= new InclusivePositionUpdater(getCategory());
228             document.addPositionUpdater(fUpdater);
229
230             model.addLinkingListener(new ILinkedModeListener() {
231
232                 /*
233                  * @see org.eclipse.jface.text.link.ILinkedModeListener#left(org.eclipse.jface.text.link.LinkedModeModel, int)
234                  */

235                 public void left(LinkedModeModel environment, int flags) {
236                     ensurePositionCategoryRemoved(document);
237                 }
238
239                 public void suspend(LinkedModeModel environment) {}
240                 public void resume(LinkedModeModel environment, int flags) {}
241             });
242         }
243     }
244
245     private void ensurePositionCategoryRemoved(IDocument document) {
246         if (document.containsPositionCategory(getCategory())) {
247             try {
248                 document.removePositionCategory(getCategory());
249             } catch (BadPositionCategoryException e) {
250                 // ignore
251
}
252             document.removePositionUpdater(fUpdater);
253         }
254     }
255
256     private String JavaDoc getCategory() {
257         return "TemplateProposalCategory_" + toString(); //$NON-NLS-1$
258
}
259
260     private int getCaretOffset(TemplateBuffer buffer) {
261
262         TemplateVariable[] variables= buffer.getVariables();
263         for (int i= 0; i != variables.length; i++) {
264             TemplateVariable variable= variables[i];
265             if (variable.getType().equals(GlobalTemplateVariables.Cursor.NAME))
266                 return variable.getOffsets()[0];
267         }
268
269         return buffer.getString().length();
270     }
271
272     /**
273      * Returns the offset of the range in the document that will be replaced by
274      * applying this template.
275      *
276      * @return the offset of the range in the document that will be replaced by
277      * applying this template
278      * @since 3.1
279      */

280     protected final int getReplaceOffset() {
281         int start;
282         if (fContext instanceof DocumentTemplateContext) {
283             DocumentTemplateContext docContext = (DocumentTemplateContext)fContext;
284             start= docContext.getStart();
285         } else {
286             start= fRegion.getOffset();
287         }
288         return start;
289     }
290
291     /**
292      * Returns the end offset of the range in the document that will be replaced
293      * by applying this template.
294      *
295      * @return the end offset of the range in the document that will be replaced
296      * by applying this template
297      * @since 3.1
298      */

299     protected final int getReplaceEndOffset() {
300         int end;
301         if (fContext instanceof DocumentTemplateContext) {
302             DocumentTemplateContext docContext = (DocumentTemplateContext)fContext;
303             end= docContext.getEnd();
304         } else {
305             end= fRegion.getOffset() + fRegion.getLength();
306         }
307         return end;
308     }
309
310     /*
311      * @see ICompletionProposal#getSelection(IDocument)
312      */

313     public Point getSelection(IDocument document) {
314         return new Point(fSelectedRegion.getOffset(), fSelectedRegion.getLength());
315     }
316
317     /*
318      * @see ICompletionProposal#getAdditionalProposalInfo()
319      */

320     public String JavaDoc getAdditionalProposalInfo() {
321         try {
322             fContext.setReadOnly(true);
323             TemplateBuffer templateBuffer;
324             try {
325                 templateBuffer= fContext.evaluate(fTemplate);
326             } catch (TemplateException e) {
327                 return null;
328             }
329
330             return templateBuffer.getString();
331
332         } catch (BadLocationException e) {
333             return null;
334         }
335     }
336
337     /*
338      * @see ICompletionProposal#getDisplayString()
339      */

340     public String JavaDoc getDisplayString() {
341         if (fDisplayString == null) {
342             String JavaDoc[] arguments= new String JavaDoc[] { fTemplate.getName(), fTemplate.getDescription() };
343             fDisplayString= JFaceTextTemplateMessages.getFormattedString("TemplateProposal.displayString", arguments); //$NON-NLS-1$
344
}
345         return fDisplayString;
346     }
347
348     /*
349      * @see ICompletionProposal#getImage()
350      */

351     public Image getImage() {
352         return fImage;
353     }
354
355     /*
356      * @see ICompletionProposal#getContextInformation()
357      */

358     public IContextInformation getContextInformation() {
359         return null;
360     }
361
362     private void openErrorDialog(Shell shell, Exception JavaDoc e) {
363         MessageDialog.openError(shell, JFaceTextTemplateMessages.getString("TemplateProposal.errorDialog.title"), e.getMessage()); //$NON-NLS-1$
364
}
365
366     /**
367      * Returns the relevance.
368      *
369      * @return the relevance
370      */

371     public int getRelevance() {
372         return fRelevance;
373     }
374
375     /*
376      * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getInformationControlCreator()
377      */

378     public IInformationControlCreator getInformationControlCreator() {
379         return fInformationControlCreator;
380     }
381
382     /*
383      * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer, boolean)
384      */

385     public void selected(ITextViewer viewer, boolean smartToggle) {
386     }
387
388     /*
389      * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
390      */

391     public void unselected(ITextViewer viewer) {
392     }
393
394     /*
395      * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument, int, org.eclipse.jface.text.DocumentEvent)
396      */

397     public boolean validate(IDocument document, int offset, DocumentEvent event) {
398         try {
399             int replaceOffset= getReplaceOffset();
400             if (offset >= replaceOffset) {
401                 String JavaDoc content= document.get(replaceOffset, offset - replaceOffset);
402                 return fTemplate.getName().toLowerCase().startsWith(content.toLowerCase());
403             }
404         } catch (BadLocationException e) {
405             // concurrent modification - ignore
406
}
407         return false;
408     }
409
410     /*
411      * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getPrefixCompletionText(org.eclipse.jface.text.IDocument, int)
412      */

413     public CharSequence JavaDoc getPrefixCompletionText(IDocument document, int completionOffset) {
414         return fTemplate.getName();
415     }
416
417     /*
418      * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getPrefixCompletionStart(org.eclipse.jface.text.IDocument, int)
419      */

420     public int getPrefixCompletionStart(IDocument document, int completionOffset) {
421         return getReplaceOffset();
422     }
423
424     /*
425      * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension#apply(org.eclipse.jface.text.IDocument, char, int)
426      */

427     public void apply(IDocument document, char trigger, int offset) {
428         // not called any longer
429
}
430
431     /*
432      * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension#isValidFor(org.eclipse.jface.text.IDocument, int)
433      */

434     public boolean isValidFor(IDocument document, int offset) {
435         // not called any longer
436
return false;
437     }
438
439     /*
440      * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension#getTriggerCharacters()
441      */

442     public char[] getTriggerCharacters() {
443         // no triggers
444
return new char[0];
445     }
446
447     /*
448      * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension#getContextInformationPosition()
449      */

450     public int getContextInformationPosition() {
451         return fRegion.getOffset();
452     }
453 }
454
Popular Tags