1 /******************************************************************************* 2 * Copyright (c) 2000, 2004 IBM Corporation and others. 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Common Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/cpl-v10.html 7 * 8 * Contributors: 9 * IBM Corporation - initial API and implementation 10 *******************************************************************************/ 11 package net.sourceforge.phpdt.internal.ui.text.template.contentassist; 12 13 import java.util.ArrayList; 14 15 import net.sourceforge.phpdt.core.ICompilationUnit; 16 import net.sourceforge.phpdt.internal.corext.Assert; 17 import net.sourceforge.phpdt.internal.corext.template.php.CompilationUnitContext; 18 import net.sourceforge.phpdt.internal.corext.template.php.CompilationUnitContextType; 19 import net.sourceforge.phpdt.internal.ui.PHPUiImages; 20 import net.sourceforge.phpeclipse.PHPeclipsePlugin; 21 22 import org.eclipse.jface.text.BadLocationException; 23 import org.eclipse.jface.text.IDocument; 24 import org.eclipse.jface.text.IRegion; 25 import org.eclipse.jface.text.ITextViewer; 26 import org.eclipse.jface.text.Region; 27 import org.eclipse.jface.text.templates.GlobalTemplateVariables; 28 import org.eclipse.jface.text.templates.Template; 29 import org.eclipse.jface.text.templates.TemplateContextType; 30 import org.eclipse.swt.graphics.Point; 31 32 public class TemplateEngine { 33 34 private static final String $_LINE_SELECTION = "${" + GlobalTemplateVariables.LineSelection.NAME + "}"; //$NON-NLS-1$ //$NON-NLS-2$ 35 36 private static final String $_WORD_SELECTION = "${" + GlobalTemplateVariables.WordSelection.NAME + "}"; //$NON-NLS-1$ //$NON-NLS-2$ 37 38 /** The context type. */ 39 private TemplateContextType fContextType; 40 41 /** The result proposals. */ 42 private ArrayList fProposals = new ArrayList(); 43 44 /** 45 * Creates the template engine for a particular context type. See 46 * <code>TemplateContext</code> for supported context types. 47 */ TemplateEngine(TemplateContextType contextType)48 public TemplateEngine(TemplateContextType contextType) { 49 Assert.isNotNull(contextType); 50 fContextType = contextType; 51 } 52 53 /** 54 * Empties the collector. 55 */ reset()56 public void reset() { 57 fProposals.clear(); 58 } 59 60 /** 61 * Returns the array of matching templates. 62 */ getResults()63 public TemplateProposal[] getResults() { 64 return (TemplateProposal[]) fProposals 65 .toArray(new TemplateProposal[fProposals.size()]); 66 } 67 68 /** 69 * Inspects the context of the compilation unit around 70 * <code>completionPosition</code> and feeds the collector with proposals. 71 * 72 * @param viewer 73 * the text viewer 74 * @param completionPosition 75 * the context position in the document of the text viewer 76 * @param compilationUnit 77 * the compilation unit (may be <code>null</code>) 78 */ complete(ITextViewer viewer, int completionPosition, ICompilationUnit compilationUnit)79 public void complete(ITextViewer viewer, int completionPosition, 80 ICompilationUnit compilationUnit) { 81 IDocument document = viewer.getDocument(); 82 83 if (!(fContextType instanceof CompilationUnitContextType)) 84 return; 85 86 Point selection = viewer.getSelectedRange(); 87 88 // remember selected text 89 String selectedText = null; 90 if (selection.y != 0) { 91 try { 92 selectedText = document.get(selection.x, selection.y); 93 } catch (BadLocationException e) { 94 } 95 } 96 97 CompilationUnitContext context = ((CompilationUnitContextType) fContextType) 98 .createContext(document, completionPosition, selection.y, 99 compilationUnit); 100 context.setVariable("selection", selectedText); //$NON-NLS-1$ 101 int start = context.getStart(); 102 int end = context.getEnd(); 103 IRegion region = new Region(start, end - start); 104 105 Template[] templates = PHPeclipsePlugin.getDefault().getTemplateStore() 106 .getTemplates(); 107 108 if (selection.y == 0) { 109 for (int i = 0; i != templates.length; i++) 110 if (context.canEvaluate(templates[i])) 111 fProposals.add(new TemplateProposal(templates[i], context, 112 region, PHPUiImages 113 .get(PHPUiImages.IMG_OBJS_TEMPLATE))); 114 115 } else { 116 117 if (context.getKey().length() == 0) 118 context.setForceEvaluation(true); 119 120 boolean multipleLinesSelected = areMultipleLinesSelected(viewer); 121 122 for (int i = 0; i != templates.length; i++) { 123 Template template = templates[i]; 124 if (context.canEvaluate(template) 125 && template.getContextTypeId().equals( 126 context.getContextType().getId()) 127 && (!multipleLinesSelected 128 && template.getPattern().indexOf( 129 $_WORD_SELECTION) != -1 || (multipleLinesSelected && template 130 .getPattern().indexOf($_LINE_SELECTION) != -1))) { 131 fProposals.add(new TemplateProposal(templates[i], context, 132 region, PHPUiImages 133 .get(PHPUiImages.IMG_OBJS_TEMPLATE))); 134 } 135 } 136 } 137 } 138 139 /** 140 * Returns <code>true</code> if one line is completely selected or if 141 * multiple lines are selected. Being completely selected means that all 142 * characters except the new line characters are selected. 143 * 144 * @return <code>true</code> if one or multiple lines are selected 145 * @since 2.1 146 */ areMultipleLinesSelected(ITextViewer viewer)147 private boolean areMultipleLinesSelected(ITextViewer viewer) { 148 if (viewer == null) 149 return false; 150 151 Point s = viewer.getSelectedRange(); 152 if (s.y == 0) 153 return false; 154 155 try { 156 157 IDocument document = viewer.getDocument(); 158 int startLine = document.getLineOfOffset(s.x); 159 int endLine = document.getLineOfOffset(s.x + s.y); 160 IRegion line = document.getLineInformation(startLine); 161 return startLine != endLine 162 || (s.x == line.getOffset() && s.y == line.getLength()); 163 164 } catch (BadLocationException x) { 165 return false; 166 } 167 } 168 } 169