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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.text.template.contentassist;
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
17 import org.eclipse.jface.text.Assert;
18 import org.eclipse.jface.text.BadLocationException;
19 import org.eclipse.jface.text.DocumentEvent;
20 import org.eclipse.jface.text.IDocument;
21 import org.eclipse.jface.text.ITextViewer;
22 import org.eclipse.jface.text.contentassist.ICompletionProposal;
23 import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
24 import org.eclipse.jface.text.contentassist.IContextInformation;
25 import org.eclipse.swt.graphics.Image;
26 import org.eclipse.swt.graphics.Point;
30 * Global state for templates. Selecting a proposal for the master template variable
31 * will cause the value (and the proposals) for the slave variables to change.
35 public class MultiVariableGuess {
38 * Implementation of the <code>ICompletionProposal</code> interface and extension.
40 class Proposal implements ICompletionProposal, ICompletionProposalExtension2 {
42 /** The string to be displayed in the completion proposal popup */
43 private String fDisplayString;
44 /** The replacement string */
45 String fReplacementString;
46 /** The replacement offset */
47 private int fReplacementOffset;
48 /** The replacement length */
49 private int fReplacementLength;
50 /** The cursor position after this proposal has been applied */
51 private int fCursorPosition;
52 /** The image to be displayed in the completion proposal popup */
54 /** The context information of this proposal */
55 private IContextInformation fContextInformation;
56 /** The additional info of this proposal */
57 private String fAdditionalProposalInfo;
60 * Creates a new completion proposal based on the provided information. The replacement string is
61 * considered being the display string too. All remaining fields are set to <code>null</code>.
63 * @param replacementString the actual string to be inserted into the document
64 * @param replacementOffset the offset of the text to be replaced
65 * @param replacementLength the length of the text to be replaced
66 * @param cursorPosition the position of the cursor following the insert relative to replacementOffset
68 public Proposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition) {
69 this(replacementString, replacementOffset, replacementLength, cursorPosition, null, null, null, null);
73 * Creates a new completion proposal. All fields are initialized based on the provided information.
75 * @param replacementString the actual string to be inserted into the document
76 * @param replacementOffset the offset of the text to be replaced
77 * @param replacementLength the length of the text to be replaced
78 * @param cursorPosition the position of the cursor following the insert relative to replacementOffset
79 * @param image the image to display for this proposal
80 * @param displayString the string to be displayed for the proposal
81 * @param contextInformation the context information associated with this proposal
82 * @param additionalProposalInfo the additional information associated with this proposal
84 public Proposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, Image image, String displayString, IContextInformation contextInformation, String additionalProposalInfo) {
85 Assert.isNotNull(replacementString);
86 Assert.isTrue(replacementOffset >= 0);
87 Assert.isTrue(replacementLength >= 0);
88 Assert.isTrue(cursorPosition >= 0);
90 fReplacementString= replacementString;
91 fReplacementOffset= replacementOffset;
92 fReplacementLength= replacementLength;
93 fCursorPosition= cursorPosition;
95 fDisplayString= displayString;
96 fContextInformation= contextInformation;
97 fAdditionalProposalInfo= additionalProposalInfo;
101 * @see ICompletionProposal#apply(IDocument)
103 public void apply(IDocument document) {
105 document.replace(fReplacementOffset, fReplacementLength, fReplacementString);
106 } catch (BadLocationException x) {
112 * @see ICompletionProposal#getSelection(IDocument)
114 public Point getSelection(IDocument document) {
115 return new Point(fReplacementOffset + fCursorPosition, 0);
119 * @see ICompletionProposal#getContextInformation()
121 public IContextInformation getContextInformation() {
122 return fContextInformation;
126 * @see ICompletionProposal#getImage()
128 public Image getImage() {
133 * @see ICompletionProposal#getDisplayString()
135 public String getDisplayString() {
136 if (fDisplayString != null)
137 return fDisplayString;
138 return fReplacementString;
142 * @see ICompletionProposal#getAdditionalProposalInfo()
144 public String getAdditionalProposalInfo() {
145 return fAdditionalProposalInfo;
149 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer, char, int, int)
151 public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
152 apply(viewer.getDocument());
156 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer, boolean)
158 public void selected(ITextViewer viewer, boolean smartToggle) {
162 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
164 public void unselected(ITextViewer viewer) {
168 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument, int, org.eclipse.jface.text.DocumentEvent)
170 public boolean validate(IDocument document, int offset, DocumentEvent event) {
172 String content= document.get(fReplacementOffset, fReplacementLength);
173 if (content.startsWith(fReplacementString))
175 } catch (BadLocationException e) {
176 // ignore concurrently modified document
182 private final List fSlaves= new ArrayList();
184 private MultiVariable fMaster;
189 public MultiVariableGuess(MultiVariable mv) {
197 public ICompletionProposal[] getProposals(MultiVariable variable, int offset, int length) {
198 if (variable.equals(fMaster)) {
199 String[] choices= variable.getValues();
201 ICompletionProposal[] ret= new ICompletionProposal[choices.length];
202 for (int i= 0; i < ret.length; i++) {
203 ret[i]= new Proposal(choices[i], offset, length, offset + length) {
206 * @see org.eclipse.jface.text.link.MultiVariableGuess.Proposal#apply(org.eclipse.jface.text.IDocument)
208 public void apply(IDocument document) {
209 super.apply(document);
212 Object old= fMaster.getSet();
213 fMaster.setSet(fReplacementString);
214 if (!fReplacementString.equals(old)) {
215 for (Iterator it= fSlaves.iterator(); it.hasNext();) {
216 VariablePosition pos= (VariablePosition) it.next();
217 String[] values= pos.getVariable().getValues(fReplacementString);
219 document.replace(pos.getOffset(), pos.getLength(), values[0]);
222 } catch (BadLocationException e) {
223 // ignore and continue
234 String[] choices= variable.getValues(fMaster.getSet());
236 if (choices == null || choices.length < 2)
239 ICompletionProposal[] ret= new ICompletionProposal[choices.length];
240 for (int i= 0; i < ret.length; i++) {
241 ret[i]= new Proposal(choices[i], offset, length, offset + length);
251 public void addSlave(VariablePosition position) {
252 fSlaves.add(position);