KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > text > template > contentassist > MultiVariableGuess


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.ui.text.template.contentassist;
12
13 import java.util.HashMap JavaDoc;
14 import java.util.HashSet JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.Map JavaDoc;
17 import java.util.Set JavaDoc;
18
19 import org.eclipse.core.runtime.Assert;
20
21 import org.eclipse.swt.graphics.Image;
22 import org.eclipse.swt.graphics.Point;
23
24 import org.eclipse.jface.text.BadLocationException;
25 import org.eclipse.jface.text.DocumentEvent;
26 import org.eclipse.jface.text.IDocument;
27 import org.eclipse.jface.text.ITextViewer;
28 import org.eclipse.jface.text.contentassist.ICompletionProposal;
29 import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
30 import org.eclipse.jface.text.contentassist.IContextInformation;
31
32
33 /**
34  * Global state for templates. Selecting a proposal for the master template variable
35  * will cause the value (and the proposals) for the slave variables to change.
36  *
37  * @see MultiVariable
38  */

39 public class MultiVariableGuess {
40
41     /**
42      * Implementation of the <code>ICompletionProposal</code> interface and extension.
43      */

44     private static class Proposal implements ICompletionProposal, ICompletionProposalExtension2 {
45
46         /** The string to be displayed in the completion proposal popup */
47         private String JavaDoc fDisplayString;
48         /** The replacement string */
49         String JavaDoc fReplacementString;
50         /** The replacement offset */
51         private int fReplacementOffset;
52         /** The replacement length */
53         private int fReplacementLength;
54         /** The cursor position after this proposal has been applied */
55         private int fCursorPosition;
56         /** The image to be displayed in the completion proposal popup */
57         private Image fImage;
58         /** The context information of this proposal */
59         private IContextInformation fContextInformation;
60         /** The additional info of this proposal */
61         private String JavaDoc fAdditionalProposalInfo;
62
63         /**
64          * Creates a new completion proposal based on the provided information. The replacement string is
65          * considered being the display string too. All remaining fields are set to <code>null</code>.
66          *
67          * @param replacementString the actual string to be inserted into the document
68          * @param replacementOffset the offset of the text to be replaced
69          * @param replacementLength the length of the text to be replaced
70          * @param cursorPosition the position of the cursor following the insert relative to replacementOffset
71          */

72         public Proposal(String JavaDoc replacementString, int replacementOffset, int replacementLength, int cursorPosition) {
73             this(replacementString, replacementOffset, replacementLength, cursorPosition, null, null, null, null);
74         }
75
76         /**
77          * Creates a new completion proposal. All fields are initialized based on the provided information.
78          *
79          * @param replacementString the actual string to be inserted into the document
80          * @param replacementOffset the offset of the text to be replaced
81          * @param replacementLength the length of the text to be replaced
82          * @param cursorPosition the position of the cursor following the insert relative to replacementOffset
83          * @param image the image to display for this proposal
84          * @param displayString the string to be displayed for the proposal
85          * @param contextInformation the context information associated with this proposal
86          * @param additionalProposalInfo the additional information associated with this proposal
87          */

88         public Proposal(String JavaDoc replacementString, int replacementOffset, int replacementLength, int cursorPosition, Image image, String JavaDoc displayString, IContextInformation contextInformation, String JavaDoc additionalProposalInfo) {
89             Assert.isNotNull(replacementString);
90             Assert.isTrue(replacementOffset >= 0);
91             Assert.isTrue(replacementLength >= 0);
92             Assert.isTrue(cursorPosition >= 0);
93
94             fReplacementString= replacementString;
95             fReplacementOffset= replacementOffset;
96             fReplacementLength= replacementLength;
97             fCursorPosition= cursorPosition;
98             fImage= image;
99             fDisplayString= displayString;
100             fContextInformation= contextInformation;
101             fAdditionalProposalInfo= additionalProposalInfo;
102         }
103
104         /*
105          * @see ICompletionProposal#apply(IDocument)
106          */

107         public void apply(IDocument document) {
108             try {
109                 document.replace(fReplacementOffset, fReplacementLength, fReplacementString);
110             } catch (BadLocationException x) {
111                 // ignore
112
}
113         }
114
115         /*
116          * @see ICompletionProposal#getSelection(IDocument)
117          */

118         public Point getSelection(IDocument document) {
119             return new Point(fReplacementOffset + fCursorPosition, 0);
120         }
121
122         /*
123          * @see ICompletionProposal#getContextInformation()
124          */

125         public IContextInformation getContextInformation() {
126             return fContextInformation;
127         }
128
129         /*
130          * @see ICompletionProposal#getImage()
131          */

132         public Image getImage() {
133             return fImage;
134         }
135
136         /*
137          * @see ICompletionProposal#getDisplayString()
138          */

139         public String JavaDoc getDisplayString() {
140             if (fDisplayString != null)
141                 return fDisplayString;
142             return fReplacementString;
143         }
144
145         /*
146          * @see ICompletionProposal#getAdditionalProposalInfo()
147          */

148         public String JavaDoc getAdditionalProposalInfo() {
149             return fAdditionalProposalInfo;
150         }
151
152         /*
153          * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer, char, int, int)
154          */

155         public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
156             apply(viewer.getDocument());
157         }
158
159         /*
160          * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer, boolean)
161          */

162         public void selected(ITextViewer viewer, boolean smartToggle) {
163         }
164
165         /*
166          * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
167          */

168         public void unselected(ITextViewer viewer) {
169         }
170
171         /*
172          * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument, int, org.eclipse.jface.text.DocumentEvent)
173          */

174         public boolean validate(IDocument document, int offset, DocumentEvent event) {
175             try {
176                 String JavaDoc content= document.get(fReplacementOffset, fReplacementLength);
177                 if (content.startsWith(fReplacementString))
178                     return true;
179             } catch (BadLocationException e) {
180                 // ignore concurrently modified document
181
}
182             return false;
183         }
184     }
185
186     private final Map JavaDoc fDependencies= new HashMap JavaDoc();
187     private final Map JavaDoc fBackwardDeps= new HashMap JavaDoc();
188     private final Map JavaDoc fPositions= new HashMap JavaDoc();
189
190     public MultiVariableGuess() {
191     }
192
193     public ICompletionProposal[] getProposals(final MultiVariable variable, int offset, int length) {
194         MultiVariable master= (MultiVariable) fBackwardDeps.get(variable);
195         Object JavaDoc[] choices;
196         if (master == null)
197             choices= variable.getChoices();
198         else
199             choices= variable.getChoices(master.getCurrentChoice());
200         
201         if (choices == null)
202             return null;
203
204         if (fDependencies.containsKey(variable)) {
205             ICompletionProposal[] ret= new ICompletionProposal[choices.length];
206             for (int i= 0; i < ret.length; i++) {
207                 final Object JavaDoc choice= choices[i];
208                 ret[i]= new Proposal(variable.toString(choice), offset, length, offset + length) {
209                     public void apply(IDocument document) {
210                         super.apply(document);
211                         Object JavaDoc oldChoice= variable.getCurrentChoice();
212                         variable.setCurrentChoice(choice);
213                         updateSlaves(variable, document, oldChoice);
214                     }
215                 };
216             }
217
218             return ret;
219
220         } else {
221             if (choices.length < 2)
222                 return null;
223
224             ICompletionProposal[] ret= new ICompletionProposal[choices.length];
225             for (int i= 0; i < ret.length; i++)
226                 ret[i]= new Proposal(variable.toString(choices[i]), offset, length, offset + length);
227
228             return ret;
229         }
230     }
231     
232     private void updateSlaves(MultiVariable variable, IDocument document, Object JavaDoc oldChoice) {
233         Object JavaDoc choice= variable.getCurrentChoice();
234         if (!oldChoice.equals(choice)) {
235             Set JavaDoc slaves= (Set JavaDoc) fDependencies.get(variable);
236             for (Iterator JavaDoc it= slaves.iterator(); it.hasNext();) {
237                 MultiVariable slave= (MultiVariable) it.next();
238                 VariablePosition pos= (VariablePosition) fPositions.get(slave);
239
240                 Object JavaDoc slavesOldChoice= slave.getCurrentChoice();
241                 slave.setKey(choice); // resets the current choice
242
try {
243                     document.replace(pos.getOffset(), pos.getLength(), slave.getDefaultValue());
244                 } catch (BadLocationException x) {
245                     // ignore and continue
246
}
247                 // handle slaves recursively
248
if (fDependencies.containsKey(slave))
249                     updateSlaves(slave, document, slavesOldChoice);
250             }
251         }
252     }
253
254     /**
255      * @param position
256      */

257     public void addSlave(VariablePosition position) {
258         fPositions.put(position.getVariable(), position);
259     }
260
261     /**
262      * @param master
263      * @param slave
264      * @since 3.3
265      */

266     public void addDependency(MultiVariable master, MultiVariable slave) {
267         // check for cycles and multi-slaves
268
if (fBackwardDeps.containsKey(slave))
269             throw new IllegalArgumentException JavaDoc("slave can only serve one master"); //$NON-NLS-1$
270
Object JavaDoc parent= master;
271         while (parent != null) {
272             parent= fBackwardDeps.get(parent);
273             if (parent == slave)
274                 throw new IllegalArgumentException JavaDoc("cycle detected"); //$NON-NLS-1$
275
}
276         
277         Set JavaDoc slaves= (Set JavaDoc) fDependencies.get(master);
278         if (slaves == null) {
279             slaves= new HashSet JavaDoc();
280             fDependencies.put(master, slaves);
281         }
282         fBackwardDeps.put(slave, master);
283         slaves.add(slave);
284     }
285 }
286
Popular Tags