001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.text.template.contentassist;
011:
012: import java.util.ArrayList;
013: import java.util.HashMap;
014: import java.util.Iterator;
015: import java.util.Map;
016: import java.util.Map.Entry;
017:
018: import org.eclipse.core.runtime.Assert;
019:
020: import org.eclipse.swt.graphics.Image;
021: import org.eclipse.swt.graphics.Point;
022:
023: import org.eclipse.jface.text.BadLocationException;
024: import org.eclipse.jface.text.IDocument;
025: import org.eclipse.jface.text.IRegion;
026: import org.eclipse.jface.text.ITextViewer;
027: import org.eclipse.jface.text.Position;
028: import org.eclipse.jface.text.Region;
029: import org.eclipse.jface.text.templates.GlobalTemplateVariables;
030: import org.eclipse.jface.text.templates.Template;
031: import org.eclipse.jface.text.templates.TemplateContextType;
032:
033: import org.eclipse.jdt.core.ICompilationUnit;
034:
035: import org.eclipse.jdt.internal.corext.template.java.CompilationUnitContext;
036: import org.eclipse.jdt.internal.corext.template.java.CompilationUnitContextType;
037: import org.eclipse.jdt.internal.corext.template.java.SWTContextType;
038:
039: import org.eclipse.jdt.internal.ui.JavaPlugin;
040: import org.eclipse.jdt.internal.ui.JavaPluginImages;
041:
042: public class TemplateEngine {
043:
044: private static final String $_LINE_SELECTION = "${" + GlobalTemplateVariables.LineSelection.NAME + "}"; //$NON-NLS-1$ //$NON-NLS-2$
045: private static final String $_WORD_SELECTION = "${" + GlobalTemplateVariables.WordSelection.NAME + "}"; //$NON-NLS-1$ //$NON-NLS-2$
046:
047: /** The context type. */
048: private TemplateContextType fContextType;
049: /** The result proposals. */
050: private ArrayList fProposals = new ArrayList();
051: /** Positions created on the key documents to remove in reset. */
052: private final Map fPositions = new HashMap();
053:
054: /**
055: * Creates the template engine for the given <code>contextType</code>.
056: * <p>
057: * The <code>JavaPlugin.getDefault().getTemplateContextRegistry()</code>
058: * defines the supported context types.</p>
059: *
060: * @param contextType the context type
061: */
062: public TemplateEngine(TemplateContextType contextType) {
063: Assert.isNotNull(contextType);
064: fContextType = contextType;
065: }
066:
067: /**
068: * Empties the collector.
069: */
070: public void reset() {
071: fProposals.clear();
072: for (Iterator it = fPositions.entrySet().iterator(); it
073: .hasNext();) {
074: Entry entry = (Entry) it.next();
075: IDocument doc = (IDocument) entry.getKey();
076: Position position = (Position) entry.getValue();
077: doc.removePosition(position);
078: }
079: fPositions.clear();
080: }
081:
082: /**
083: * Returns the array of matching templates.
084: *
085: * @return the template proposals
086: */
087: public TemplateProposal[] getResults() {
088: return (TemplateProposal[]) fProposals
089: .toArray(new TemplateProposal[fProposals.size()]);
090: }
091:
092: /**
093: * Inspects the context of the compilation unit around <code>completionPosition</code>
094: * and feeds the collector with proposals.
095: * @param viewer the text viewer
096: * @param completionPosition the context position in the document of the text viewer
097: * @param compilationUnit the compilation unit (may be <code>null</code>)
098: */
099: public void complete(ITextViewer viewer, int completionPosition,
100: ICompilationUnit compilationUnit) {
101: IDocument document = viewer.getDocument();
102:
103: if (!(fContextType instanceof CompilationUnitContextType))
104: return;
105:
106: Point selection = viewer.getSelectedRange();
107: Position position = new Position(completionPosition,
108: selection.y);
109:
110: // remember selected text
111: String selectedText = null;
112: if (selection.y != 0) {
113: try {
114: selectedText = document.get(selection.x, selection.y);
115: document.addPosition(position);
116: fPositions.put(document, position);
117: } catch (BadLocationException e) {
118: }
119: }
120:
121: CompilationUnitContext context = ((CompilationUnitContextType) fContextType)
122: .createContext(document, position, compilationUnit);
123: context.setVariable("selection", selectedText); //$NON-NLS-1$
124: int start = context.getStart();
125: int end = context.getEnd();
126: IRegion region = new Region(start, end - start);
127:
128: Template[] templates = JavaPlugin.getDefault()
129: .getTemplateStore().getTemplates();
130:
131: if (selection.y == 0) {
132: for (int i = 0; i != templates.length; i++)
133: if (context.canEvaluate(templates[i]))
134: fProposals.add(new TemplateProposal(templates[i],
135: context, region, getImage()));
136:
137: } else {
138:
139: if (context.getKey().length() == 0)
140: context.setForceEvaluation(true);
141:
142: boolean multipleLinesSelected = areMultipleLinesSelected(viewer);
143:
144: for (int i = 0; i != templates.length; i++) {
145: Template template = templates[i];
146: if (context.canEvaluate(template)
147: && template.getContextTypeId().equals(
148: context.getContextType().getId())
149: && (!multipleLinesSelected
150: && template.getPattern().indexOf(
151: $_WORD_SELECTION) != -1 || (multipleLinesSelected && template
152: .getPattern().indexOf($_LINE_SELECTION) != -1))) {
153: fProposals.add(new TemplateProposal(templates[i],
154: context, region, getImage()));
155: }
156: }
157: }
158: }
159:
160: private Image getImage() {
161: if (SWTContextType.ID.equals(fContextType.getId()))
162: return JavaPluginImages
163: .get(JavaPluginImages.IMG_OBJS_SWT_TEMPLATE);
164: else
165: return JavaPluginImages
166: .get(JavaPluginImages.IMG_OBJS_TEMPLATE);
167: }
168:
169: /**
170: * Returns <code>true</code> if one line is completely selected or if multiple lines are selected.
171: * Being completely selected means that all characters except the new line characters are
172: * selected.
173: *
174: * @param viewer the text viewer
175: * @return <code>true</code> if one or multiple lines are selected
176: * @since 2.1
177: */
178: private boolean areMultipleLinesSelected(ITextViewer viewer) {
179: if (viewer == null)
180: return false;
181:
182: Point s = viewer.getSelectedRange();
183: if (s.y == 0)
184: return false;
185:
186: try {
187:
188: IDocument document = viewer.getDocument();
189: int startLine = document.getLineOfOffset(s.x);
190: int endLine = document.getLineOfOffset(s.x + s.y);
191: IRegion line = document.getLineInformation(startLine);
192: return startLine != endLine
193: || (s.x == line.getOffset() && s.y == line
194: .getLength());
195:
196: } catch (BadLocationException x) {
197: return false;
198: }
199: }
200: }
|