Syntax highlighting is changeable.
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / template / contentassist / MultiVariableGuess.java
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 import java.util.Iterator;
15 import java.util.List;
16
17 import org.eclipse.swt.graphics.Image;
18 import org.eclipse.swt.graphics.Point;
19
20 import org.eclipse.jface.text.Assert;
21 import org.eclipse.jface.text.BadLocationException;
22 import org.eclipse.jface.text.DocumentEvent;
23 import org.eclipse.jface.text.IDocument;
24 import org.eclipse.jface.text.ITextViewer;
25 import org.eclipse.jface.text.contentassist.ICompletionProposal;
26 import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
27 import org.eclipse.jface.text.contentassist.IContextInformation;
28
29
30 /**
31  * Global state for templates. Selecting a proposal for the master template variable
32  * will cause the value (and the proposals) for the slave variables to change.
33  * 
34  * @see MultiVariable
35  */
36 public class MultiVariableGuess {
37         
38         /**
39          * Implementation of the <code>ICompletionProposal</code> interface and extension.
40          */
41         class Proposal implements ICompletionProposal, ICompletionProposalExtension2 {
42                 
43                 /** The string to be displayed in the completion proposal popup */
44                 private String fDisplayString;
45                 /** The replacement string */
46                 String fReplacementString;
47                 /** The replacement offset */
48                 private int fReplacementOffset;
49                 /** The replacement length */
50                 private int fReplacementLength;
51                 /** The cursor position after this proposal has been applied */
52                 private int fCursorPosition;
53                 /** The image to be displayed in the completion proposal popup */
54                 private Image fImage;
55                 /** The context information of this proposal */
56                 private IContextInformation fContextInformation;
57                 /** The additional info of this proposal */
58                 private String fAdditionalProposalInfo;
59
60                 /**
61                  * Creates a new completion proposal based on the provided information.  The replacement string is
62                  * considered being the display string too. All remaining fields are set to <code>null</code>.
63                  *
64                  * @param replacementString the actual string to be inserted into the document
65                  * @param replacementOffset the offset of the text to be replaced
66                  * @param replacementLength the length of the text to be replaced
67                  * @param cursorPosition the position of the cursor following the insert relative to replacementOffset
68                  */
69                 public Proposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition) {
70                         this(replacementString, replacementOffset, replacementLength, cursorPosition, null, null, null, null);
71                 }
72
73                 /**
74                  * Creates a new completion proposal. All fields are initialized based on the provided information.
75                  *
76                  * @param replacementString the actual string to be inserted into the document
77                  * @param replacementOffset the offset of the text to be replaced
78                  * @param replacementLength the length of the text to be replaced
79                  * @param cursorPosition the position of the cursor following the insert relative to replacementOffset
80                  * @param image the image to display for this proposal
81                  * @param displayString the string to be displayed for the proposal
82                  * @param contextInformation the context information associated with this proposal
83                  * @param additionalProposalInfo the additional information associated with this proposal
84                  */
85                 public Proposal(String replacementString, int replacementOffset, int replacementLength, int cursorPosition, Image image, String displayString, IContextInformation contextInformation, String additionalProposalInfo) {
86                         Assert.isNotNull(replacementString);
87                         Assert.isTrue(replacementOffset >= 0);
88                         Assert.isTrue(replacementLength >= 0);
89                         Assert.isTrue(cursorPosition >= 0);
90                         
91                         fReplacementString= replacementString;
92                         fReplacementOffset= replacementOffset;
93                         fReplacementLength= replacementLength;
94                         fCursorPosition= cursorPosition;
95                         fImage= image;
96                         fDisplayString= displayString;
97                         fContextInformation= contextInformation;
98                         fAdditionalProposalInfo= additionalProposalInfo;
99                 }
100
101                 /*
102                  * @see ICompletionProposal#apply(IDocument)
103                  */
104                 public void apply(IDocument document) {
105                         try {
106                                 document.replace(fReplacementOffset, fReplacementLength, fReplacementString);
107                         } catch (BadLocationException x) {
108                                 // ignore
109                         }
110                 }
111                 
112                 /*
113                  * @see ICompletionProposal#getSelection(IDocument)
114                  */
115                 public Point getSelection(IDocument document) {
116                         return new Point(fReplacementOffset + fCursorPosition, 0);
117                 }
118
119                 /*
120                  * @see ICompletionProposal#getContextInformation()
121                  */
122                 public IContextInformation getContextInformation() {
123                         return fContextInformation;
124                 }
125
126                 /*
127                  * @see ICompletionProposal#getImage()
128                  */
129                 public Image getImage() {
130                         return fImage;
131                 }
132
133                 /*
134                  * @see ICompletionProposal#getDisplayString()
135                  */
136                 public String getDisplayString() {
137                         if (fDisplayString != null)
138                                 return fDisplayString;
139                         return fReplacementString;
140                 }
141
142                 /*
143                  * @see ICompletionProposal#getAdditionalProposalInfo()
144                  */
145                 public String getAdditionalProposalInfo() {
146                         return fAdditionalProposalInfo;
147                 }
148                 
149                 /*
150                  * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer, char, int, int)
151                  */
152                 public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
153                         apply(viewer.getDocument());
154                 }
155                 
156                 /*
157                  * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer, boolean)
158                  */
159                 public void selected(ITextViewer viewer, boolean smartToggle) {
160                 }
161                 
162                 /*
163                  * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
164                  */
165                 public void unselected(ITextViewer viewer) {
166                 }
167                 
168                 /*
169                  * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument, int, org.eclipse.jface.text.DocumentEvent)
170                  */
171                 public boolean validate(IDocument document, int offset, DocumentEvent event) {
172                         try {
173                                 String content= document.get(fReplacementOffset, fReplacementLength);
174                                 if (content.startsWith(fReplacementString))
175                                         return true;
176                         } catch (BadLocationException e) {
177                                 // ignore concurrently modified document
178                         }
179                         return false;
180                 }
181         }
182         
183         private final List fSlaves= new ArrayList();
184         
185         private MultiVariable fMaster;
186
187         /**
188          * @param mv
189          */
190         public MultiVariableGuess(MultiVariable mv) {
191                 fMaster= mv;
192         }
193
194         /**
195          * @param variable
196          * @return
197          */
198         public ICompletionProposal[] getProposals(MultiVariable variable, int offset, int length) {
199                 if (variable.equals(fMaster)) {
200                         String[] choices= variable.getValues();
201                         
202                         ICompletionProposal[] ret= new ICompletionProposal[choices.length];
203                         for (int i= 0; i < ret.length; i++) {
204                                 ret[i]= new Proposal(choices[i], offset, length, offset + length) {
205                                         
206                                         /*
207                                          * @see org.eclipse.jface.text.link.MultiVariableGuess.Proposal#apply(org.eclipse.jface.text.IDocument)
208                                          */
209                                         public void apply(IDocument document) {
210                                                 super.apply(document);
211
212                                                 try {
213                                                         Object old= fMaster.getSet();
214                                                         fMaster.setSet(fReplacementString);
215                                                         if (!fReplacementString.equals(old)) {
216                                                                 for (Iterator it= fSlaves.iterator(); it.hasNext();) {
217                                                                         VariablePosition pos= (VariablePosition) it.next();
218                                                                         String[] values= pos.getVariable().getValues(fReplacementString);
219                                                                         if (values != null)
220                                                                                 document.replace(pos.getOffset(), pos.getLength(), values[0]);
221                                                                 }
222                                                         }
223                                                 } catch (BadLocationException e) {
224                                                         // ignore and continue
225                                                 }
226
227                                         }
228                                 };
229                         }
230                         
231                         return ret;
232                         
233                 } else {
234                 
235                         String[] choices= variable.getValues(fMaster.getSet());
236                         
237                         if (choices == null || choices.length < 2)
238                                 return null;
239                         
240                         ICompletionProposal[] ret= new ICompletionProposal[choices.length];
241                         for (int i= 0; i < ret.length; i++) {
242                                 ret[i]= new Proposal(choices[i], offset, length, offset + length);
243                         }
244                         
245                         return ret;
246                 }
247         }
248
249         /**
250          * @param position
251          */
252         public void addSlave(VariablePosition position) {
253                 fSlaves.add(position);
254         }
255
256 }