fixed bug in template expansion
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / template / TemplateProposal.java
1 /*
2  * (c) Copyright IBM Corp. 2000, 2001.
3  * All Rights Reserved.
4  */
5 package net.sourceforge.phpdt.internal.ui.text.template;
6
7 import net.sourceforge.phpdt.internal.corext.template.Template;
8 import net.sourceforge.phpdt.internal.corext.template.TemplateBuffer;
9 import net.sourceforge.phpdt.internal.corext.template.TemplateContext;
10 import net.sourceforge.phpdt.internal.corext.template.TemplateMessages;
11 import net.sourceforge.phpdt.internal.corext.template.TemplatePosition;
12 import net.sourceforge.phpdt.internal.corext.template.java.CompilationUnitContext;
13 import net.sourceforge.phpdt.internal.corext.template.java.JavaTemplateMessages;
14 import net.sourceforge.phpdt.internal.ui.text.java.IJavaCompletionProposal;
15 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
16 import org.eclipse.core.runtime.CoreException;
17 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
18 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
19 import org.eclipse.jface.dialogs.MessageDialog;
20 import org.eclipse.jface.text.BadLocationException;
21 import org.eclipse.jface.text.IDocument;
22 import org.eclipse.jface.text.IRegion;
23 import org.eclipse.jface.text.ITextViewer;
24 import org.eclipse.jface.text.contentassist.IContextInformation;
25 import org.eclipse.swt.graphics.Image;
26 import org.eclipse.swt.graphics.Point;
27 import org.eclipse.swt.widgets.Shell;
28 //import org.eclipse.jdt.internal.ui.text.link.LinkedPositionManager;
29 //import org.eclipse.jdt.internal.ui.text.link.LinkedPositionUI;
30 //import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
31
32 /**
33  * A template proposal.
34  */
35 public class TemplateProposal implements IJavaCompletionProposal {
36
37         private final Template fTemplate;
38         private final TemplateContext fContext;
39         private final ITextViewer fViewer;
40 //      private final Image fImage;
41         private final IRegion fRegion;
42
43         private TemplateBuffer fTemplateBuffer;
44         private String fOldText;
45         private IRegion fSelectedRegion; // initialized by apply()
46                 
47         /**
48          * Creates a template proposal with a template and its context.
49          * @param template  the template
50          * @param context   the context in which the template was requested.
51          * @param image     the icon of the proposal.
52          */     
53         public TemplateProposal(Template template, TemplateContext context, IRegion region, ITextViewer viewer){ //, Image image) {
54 //              Assert.isNotNull(template);
55 //              Assert.isNotNull(context);
56 //              Assert.isNotNull(region);
57 //              Assert.isNotNull(viewer);
58                 
59                 fTemplate= template;
60                 fContext= context;
61                 fViewer= viewer;
62 //              fImage= image;
63                 fRegion= region;
64         }
65
66         /*
67          * @see ICompletionProposal#apply(IDocument)
68          */
69         public void apply(IDocument document) {
70             try {               
71                     if (fTemplateBuffer == null)
72                                 fTemplateBuffer= fContext.evaluate(fTemplate);
73
74                         int start= fRegion.getOffset();
75                         int end= fRegion.getOffset() + fRegion.getLength();
76                         
77                         // insert template string
78                         String templateString= fTemplateBuffer.getString();     
79                         document.replace(start, end - start, templateString);   
80
81                         // translate positions
82                         LinkedPositionManager manager= new LinkedPositionManager(document);
83                         TemplatePosition[] variables= fTemplateBuffer.getVariables();
84                         for (int i= 0; i != variables.length; i++) {
85                                 TemplatePosition variable= variables[i];
86
87                                 if (variable.isResolved())
88                                         continue;
89                                 
90                                 int[] offsets= variable.getOffsets();
91                                 int length= variable.getLength();
92                                 
93                                 for (int j= 0; j != offsets.length; j++)
94                                         manager.addPosition(offsets[j] + start, length);
95                         }
96                         
97                         LinkedPositionUI editor= new LinkedPositionUI(fViewer, manager);
98                         editor.setFinalCaretOffset(getCaretOffset(fTemplateBuffer) + start);
99                         editor.enter();
100
101                         fSelectedRegion= editor.getSelectedRegion();
102                         
103                 } catch (BadLocationException e) {
104                         PHPeclipsePlugin.log(e);        
105                         openErrorDialog(e);                         
106
107             } catch (CoreException e) {
108                         handleException(e);
109             }       
110         }
111         
112         private static int getCaretOffset(TemplateBuffer buffer) {
113             TemplatePosition[] variables= buffer.getVariables();
114                 for (int i= 0; i != variables.length; i++) {
115                         TemplatePosition variable= variables[i];
116                         
117                         if (variable.getName().equals(JavaTemplateMessages.getString("GlobalVariables.variable.name.cursor"))) //$NON-NLS-1$
118                                 return variable.getOffsets()[0];
119                 }
120
121                 return buffer.getString().length();
122         }
123         
124         /*
125          * @see ICompletionProposal#getSelection(IDocument)
126          */
127         public Point getSelection(IDocument document) {
128                 return new Point(fSelectedRegion.getOffset(), fSelectedRegion.getLength());
129 //        return null;
130   }
131
132         /*
133          * @see ICompletionProposal#getAdditionalProposalInfo()
134          */
135         public String getAdditionalProposalInfo() {
136             try {
137                         if (fTemplateBuffer == null)
138                                 fTemplateBuffer= fContext.evaluate(fTemplate);
139
140                         return textToHTML(fTemplateBuffer.getString());
141
142             } catch (CoreException e) {
143                         handleException(e);                 
144                         return null;
145             }
146         }
147
148         /*
149          * @see ICompletionProposal#getDisplayString()
150          */
151         public String getDisplayString() {
152                 return fTemplate.getName() + TemplateMessages.getString("TemplateProposal.delimiter") + fTemplate.getDescription(); // $NON-NLS-1$ //$NON-NLS-1$
153         }
154
155         /*
156          * @see ICompletionProposal#getImage()
157          */
158         public Image getImage() {
159 //              return fImage;
160      return null;
161         }
162
163         /*
164          * @see ICompletionProposal#getContextInformation()
165          */
166         public IContextInformation getContextInformation() {
167                 return null;
168         }
169
170         private static String textToHTML(String string) {
171                 StringBuffer buffer= new StringBuffer(string.length());
172                 buffer.append("<pre>"); //$NON-NLS-1$
173         
174                 for (int i= 0; i != string.length(); i++) {
175                         char ch= string.charAt(i);
176                         
177                         switch (ch) {
178                                 case '&':
179                                         buffer.append("&amp;"); //$NON-NLS-1$
180                                         break;
181                                         
182                                 case '<':
183                                         buffer.append("&lt;"); //$NON-NLS-1$
184                                         break;
185
186                                 case '>':
187                                         buffer.append("&gt;"); //$NON-NLS-1$
188                                         break;
189
190                                 case '\t':
191                                         buffer.append("    "); //$NON-NLS-1$
192                                         break;
193
194                                 case '\n':
195                                         buffer.append("<br>"); //$NON-NLS-1$
196                                         break;
197
198                                 default:
199                                         buffer.append(ch);
200                                         break;
201                         }
202                 }
203
204                 buffer.append("</pre>"); //$NON-NLS-1$
205                 return buffer.toString();
206         }
207
208         private void openErrorDialog(BadLocationException e) {
209                 Shell shell= fViewer.getTextWidget().getShell();
210                 MessageDialog.openError(shell, TemplateMessages.getString("TemplateEvaluator.error.title"), e.getMessage()); //$NON-NLS-1$
211         }
212
213         private void handleException(CoreException e) {
214                 Shell shell= fViewer.getTextWidget().getShell();
215     PHPeclipsePlugin.log(e);
216 //              ExceptionHandler.handle(e, shell, TemplateMessages.getString("TemplateEvaluator.error.title"), null); //$NON-NLS-1$
217         }
218
219         /*
220          * @see IJavaCompletionProposal#getRelevance()
221          */
222         public int getRelevance() {
223
224                 if (fContext instanceof CompilationUnitContext) {
225                         CompilationUnitContext context= (CompilationUnitContext) fContext;
226                         switch (context.getCharacterBeforeStart()) { 
227                         // high relevance after whitespace
228                         case ' ':
229                         case '\r':
230                         case '\n':
231                         case '\t':
232                                 return 90;
233
234                         default:
235                                 return 0;
236                         }
237                 } else {
238                         return 90;                      
239                 }
240         }
241
242 }