8350ec362cccd1857f6d588630c904828f80721f
[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.php.PHPUnitContext;
13 import net.sourceforge.phpdt.internal.corext.template.php.PHPTemplateMessages;
14 import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal;
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 IPHPCompletionProposal {
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(PHPTemplateMessages.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         }
161
162         /*
163          * @see ICompletionProposal#getContextInformation()
164          */
165         public IContextInformation getContextInformation() {
166                 return null;
167         }
168
169         private static String textToHTML(String string) {
170                 StringBuffer buffer= new StringBuffer(string.length());
171                 buffer.append("<pre>"); //$NON-NLS-1$
172         
173                 for (int i= 0; i != string.length(); i++) {
174                         char ch= string.charAt(i);
175                         
176                         switch (ch) {
177                                 case '&':
178                                         buffer.append("&amp;"); //$NON-NLS-1$
179                                         break;
180                                         
181                                 case '<':
182                                         buffer.append("&lt;"); //$NON-NLS-1$
183                                         break;
184
185                                 case '>':
186                                         buffer.append("&gt;"); //$NON-NLS-1$
187                                         break;
188
189                                 case '\t':
190                                         buffer.append("    "); //$NON-NLS-1$
191                                         break;
192
193                                 case '\n':
194                                         buffer.append("<br>"); //$NON-NLS-1$
195                                         break;
196
197                                 default:
198                                         buffer.append(ch);
199                                         break;
200                         }
201                 }
202
203                 buffer.append("</pre>"); //$NON-NLS-1$
204                 return buffer.toString();
205         }
206
207         private void openErrorDialog(BadLocationException e) {
208                 Shell shell= fViewer.getTextWidget().getShell();
209                 MessageDialog.openError(shell, TemplateMessages.getString("TemplateEvaluator.error.title"), e.getMessage()); //$NON-NLS-1$
210         }
211
212         private void handleException(CoreException e) {
213                 Shell shell= fViewer.getTextWidget().getShell();
214     PHPeclipsePlugin.log(e);
215 //              ExceptionHandler.handle(e, shell, TemplateMessages.getString("TemplateEvaluator.error.title"), null); //$NON-NLS-1$
216         }
217
218         /*
219          * @see IJavaCompletionProposal#getRelevance()
220          */
221         public int getRelevance() {
222
223                 if (fContext instanceof PHPUnitContext) {
224                         PHPUnitContext context= (PHPUnitContext) fContext;
225                         switch (context.getCharacterBeforeStart()) { 
226                         // high relevance after whitespace
227                         case ' ':
228                         case '\r':
229                         case '\n':
230                         case '\t':
231                                 return 90;
232
233                         default:
234                                 return 0;
235                         }
236                 } else {
237                         return 90;                      
238                 }
239         }
240
241 }