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;
 
  29  * Global state for templates. Selecting a proposal for the master template
 
  30  * variable will cause the value (and the proposals) for the slave variables to
 
  35 public class MultiVariableGuess {
 
  38          * Implementation of the <code>ICompletionProposal</code> interface and
 
  41         class Proposal implements ICompletionProposal,
 
  42                         ICompletionProposalExtension2 {
 
  44                 /** The string to be displayed in the completion proposal popup */
 
  45                 private String fDisplayString;
 
  47                 /** The replacement string */
 
  48                 String fReplacementString;
 
  50                 /** The replacement offset */
 
  51                 private int fReplacementOffset;
 
  53                 /** The replacement length */
 
  54                 private int fReplacementLength;
 
  56                 /** The cursor position after this proposal has been applied */
 
  57                 private int fCursorPosition;
 
  59                 /** The image to be displayed in the completion proposal popup */
 
  62                 /** The context information of this proposal */
 
  63                 private IContextInformation fContextInformation;
 
  65                 /** The additional info of this proposal */
 
  66                 private String fAdditionalProposalInfo;
 
  69                  * Creates a new completion proposal based on the provided information.
 
  70                  * The replacement string is considered being the display string too.
 
  71                  * All remaining fields are set to <code>null</code>.
 
  73                  * @param replacementString
 
  74                  *            the actual string to be inserted into the document
 
  75                  * @param replacementOffset
 
  76                  *            the offset of the text to be replaced
 
  77                  * @param replacementLength
 
  78                  *            the length of the text to be replaced
 
  79                  * @param cursorPosition
 
  80                  *            the position of the cursor following the insert relative
 
  81                  *            to replacementOffset
 
  83                 public Proposal(String replacementString, int replacementOffset,
 
  84                                 int replacementLength, int cursorPosition) {
 
  85                         this(replacementString, replacementOffset, replacementLength,
 
  86                                         cursorPosition, null, null, null, null);
 
  90                  * Creates a new completion proposal. All fields are initialized based
 
  91                  * on the provided information.
 
  93                  * @param replacementString
 
  94                  *            the actual string to be inserted into the document
 
  95                  * @param replacementOffset
 
  96                  *            the offset of the text to be replaced
 
  97                  * @param replacementLength
 
  98                  *            the length of the text to be replaced
 
  99                  * @param cursorPosition
 
 100                  *            the position of the cursor following the insert relative
 
 101                  *            to replacementOffset
 
 103                  *            the image to display for this proposal
 
 104                  * @param displayString
 
 105                  *            the string to be displayed for the proposal
 
 106                  * @param contextInformation
 
 107                  *            the context information associated with this proposal
 
 108                  * @param additionalProposalInfo
 
 109                  *            the additional information associated with this proposal
 
 111                 public Proposal(String replacementString, int replacementOffset,
 
 112                                 int replacementLength, int cursorPosition, Image image,
 
 113                                 String displayString, IContextInformation contextInformation,
 
 114                                 String additionalProposalInfo) {
 
 115                         Assert.isNotNull(replacementString);
 
 116                         Assert.isTrue(replacementOffset >= 0);
 
 117                         Assert.isTrue(replacementLength >= 0);
 
 118                         Assert.isTrue(cursorPosition >= 0);
 
 120                         fReplacementString = replacementString;
 
 121                         fReplacementOffset = replacementOffset;
 
 122                         fReplacementLength = replacementLength;
 
 123                         fCursorPosition = cursorPosition;
 
 125                         fDisplayString = displayString;
 
 126                         fContextInformation = contextInformation;
 
 127                         fAdditionalProposalInfo = additionalProposalInfo;
 
 131                  * @see ICompletionProposal#apply(IDocument)
 
 133                 public void apply(IDocument document) {
 
 135                                 document.replace(fReplacementOffset, fReplacementLength,
 
 137                         } catch (BadLocationException x) {
 
 143                  * @see ICompletionProposal#getSelection(IDocument)
 
 145                 public Point getSelection(IDocument document) {
 
 146                         return new Point(fReplacementOffset + fCursorPosition, 0);
 
 150                  * @see ICompletionProposal#getContextInformation()
 
 152                 public IContextInformation getContextInformation() {
 
 153                         return fContextInformation;
 
 157                  * @see ICompletionProposal#getImage()
 
 159                 public Image getImage() {
 
 164                  * @see ICompletionProposal#getDisplayString()
 
 166                 public String getDisplayString() {
 
 167                         if (fDisplayString != null)
 
 168                                 return fDisplayString;
 
 169                         return fReplacementString;
 
 173                  * @see ICompletionProposal#getAdditionalProposalInfo()
 
 175                 public String getAdditionalProposalInfo() {
 
 176                         return fAdditionalProposalInfo;
 
 180                  * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer,
 
 183                 public void apply(ITextViewer viewer, char trigger, int stateMask,
 
 185                         apply(viewer.getDocument());
 
 189                  * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer,
 
 192                 public void selected(ITextViewer viewer, boolean smartToggle) {
 
 196                  * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
 
 198                 public void unselected(ITextViewer viewer) {
 
 202                  * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument,
 
 203                  *      int, org.eclipse.jface.text.DocumentEvent)
 
 205                 public boolean validate(IDocument document, int offset,
 
 206                                 DocumentEvent event) {
 
 208                                 String content = document.get(fReplacementOffset,
 
 210                                 if (content.startsWith(fReplacementString))
 
 212                         } catch (BadLocationException e) {
 
 213                                 // ignore concurrently modified document
 
 219         private final List fSlaves = new ArrayList();
 
 221         private MultiVariable fMaster;
 
 226         public MultiVariableGuess(MultiVariable mv) {
 
 234         public ICompletionProposal[] getProposals(MultiVariable variable,
 
 235                         int offset, int length) {
 
 236                 if (variable.equals(fMaster)) {
 
 237                         String[] choices = variable.getValues();
 
 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
 
 245                                          * @see org.eclipse.jface.text.link.MultiVariableGuess.Proposal#apply(org.eclipse.jface.text.IDocument)
 
 247                                         public void apply(IDocument document) {
 
 248                                                 super.apply(document);
 
 251                                                         Object old = fMaster.getSet();
 
 252                                                         fMaster.setSet(fReplacementString);
 
 253                                                         if (!fReplacementString.equals(old)) {
 
 254                                                                 for (Iterator it = fSlaves.iterator(); it
 
 256                                                                         VariablePosition pos = (VariablePosition) it
 
 258                                                                         String[] values = pos.getVariable()
 
 259                                                                                         .getValues(fReplacementString);
 
 261                                                                                 document.replace(pos.getOffset(), pos
 
 262                                                                                                 .getLength(), values[0]);
 
 265                                                 } catch (BadLocationException e) {
 
 266                                                         // ignore and continue
 
 277                         String[] choices = variable.getValues(fMaster.getSet());
 
 279                         if (choices == null || choices.length < 2)
 
 282                         ICompletionProposal[] ret = new ICompletionProposal[choices.length];
 
 283                         for (int i = 0; i < ret.length; i++) {
 
 284                                 ret[i] = new Proposal(choices[i], offset, length, offset
 
 295         public void addSlave(VariablePosition position) {
 
 296                 fSlaves.add(position);