1 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 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; private String fDisplayString; 60 private InclusivePositionUpdater fUpdater; 61 private IInformationControlCreator fInformationControlCreator; 62 63 71 public TemplateProposal(Template template, TemplateContext context, IRegion region, Image image) { 72 this(template, context, region, image, 0); 73 } 74 75 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 105 public final void setInformationControlCreator(IInformationControlCreator informationControlCreator) { 106 fInformationControlCreator= informationControlCreator; 107 } 108 109 115 protected final Template getTemplate() { 116 return fTemplate; 117 } 118 119 125 protected final TemplateContext getContext() { 126 return fContext; 127 } 128 129 132 public final void apply(IDocument document) { 133 } 135 136 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 String templateString= templateBuffer.getString(); 164 document.replace(start, end - start, templateString); 165 166 167 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 [] 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 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 } 252 document.removePositionUpdater(fUpdater); 253 } 254 } 255 256 private String getCategory() { 257 return "TemplateProposalCategory_" + toString(); } 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 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 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 313 public Point getSelection(IDocument document) { 314 return new Point(fSelectedRegion.getOffset(), fSelectedRegion.getLength()); 315 } 316 317 320 public String 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 340 public String getDisplayString() { 341 if (fDisplayString == null) { 342 String [] arguments= new String [] { fTemplate.getName(), fTemplate.getDescription() }; 343 fDisplayString= JFaceTextTemplateMessages.getFormattedString("TemplateProposal.displayString", arguments); } 345 return fDisplayString; 346 } 347 348 351 public Image getImage() { 352 return fImage; 353 } 354 355 358 public IContextInformation getContextInformation() { 359 return null; 360 } 361 362 private void openErrorDialog(Shell shell, Exception e) { 363 MessageDialog.openError(shell, JFaceTextTemplateMessages.getString("TemplateProposal.errorDialog.title"), e.getMessage()); } 365 366 371 public int getRelevance() { 372 return fRelevance; 373 } 374 375 378 public IInformationControlCreator getInformationControlCreator() { 379 return fInformationControlCreator; 380 } 381 382 385 public void selected(ITextViewer viewer, boolean smartToggle) { 386 } 387 388 391 public void unselected(ITextViewer viewer) { 392 } 393 394 397 public boolean validate(IDocument document, int offset, DocumentEvent event) { 398 try { 399 int replaceOffset= getReplaceOffset(); 400 if (offset >= replaceOffset) { 401 String content= document.get(replaceOffset, offset - replaceOffset); 402 return fTemplate.getName().toLowerCase().startsWith(content.toLowerCase()); 403 } 404 } catch (BadLocationException e) { 405 } 407 return false; 408 } 409 410 413 public CharSequence getPrefixCompletionText(IDocument document, int completionOffset) { 414 return fTemplate.getName(); 415 } 416 417 420 public int getPrefixCompletionStart(IDocument document, int completionOffset) { 421 return getReplaceOffset(); 422 } 423 424 427 public void apply(IDocument document, char trigger, int offset) { 428 } 430 431 434 public boolean isValidFor(IDocument document, int offset) { 435 return false; 437 } 438 439 442 public char[] getTriggerCharacters() { 443 return new char[0]; 445 } 446 447 450 public int getContextInformationPosition() { 451 return fRegion.getOffset(); 452 } 453 } 454 | Popular Tags |