1 /*******************************************************************************
\r
2 * Copyright (c) 2010 Association for Decentralized Information Management in
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.sysdyn.ui.properties.widgets.expressions;
\r
14 import java.util.ArrayList;
\r
15 import java.util.Collections;
\r
17 import org.eclipse.jface.resource.ImageDescriptor;
\r
18 import org.eclipse.jface.resource.JFaceResources;
\r
19 import org.eclipse.jface.resource.LocalResourceManager;
\r
20 import org.eclipse.jface.text.ITextViewer;
\r
21 import org.eclipse.jface.text.contentassist.CompletionProposal;
\r
22 import org.eclipse.jface.text.contentassist.ICompletionProposal;
\r
23 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
\r
24 import org.eclipse.jface.text.contentassist.IContextInformation;
\r
25 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
\r
26 import org.eclipse.swt.graphics.Image;
\r
27 import org.eclipse.swt.widgets.Control;
\r
28 import org.eclipse.swt.widgets.Table;
\r
29 import org.eclipse.swt.widgets.TableItem;
\r
30 import org.simantics.sysdyn.ui.Activator;
\r
31 import org.simantics.sysdyn.ui.utils.ExpressionUtils;
\r
35 * IContentAssistProcessor to determine which options (the functions and
\r
36 * variables available) are shown for ContentAssistant; this assist of
\r
37 * text field allows long variable names to be selected from a popup menu.
\r
38 * @author Tuomas Miettinen
\r
41 public class CompletionProcessor implements IContentAssistProcessor {
\r
43 private final Table allowedVariables;
\r
44 private ArrayList<Function> functions;
\r
45 private ArrayList<String> variables = null;
\r
46 private ArrayList<String> timeAndSelfVariables = null;
\r
48 private LocalResourceManager resourceManager;
\r
50 private final char[] allowedCharacters = {
\r
51 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','å','ä','ö',
\r
52 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','Å','Ä','Ö',
\r
53 '1','2','3','4','5','6','7','8','9','0','.','_','(',')'};
\r
55 private final String allowedConnectedCharactersRegExp = "[\\Q({[:;,<=>+-*/^\\E]";
\r
57 public CompletionProcessor(Table allowedVariables, boolean allowFunctions){
\r
58 this.allowedVariables = allowedVariables;
\r
60 if (allowFunctions) {
\r
61 //Finding functions and sorting them.
\r
62 functions = Function.getAllFunctions();
\r
63 Collections.sort(functions);
\r
68 * Collect and sort all variables.
\r
70 private void findVariables() {
\r
71 if (variables == null) {
\r
72 variables = new ArrayList<String>();
\r
73 timeAndSelfVariables = new ArrayList<String>();
\r
74 if(allowedVariables != null && !allowedVariables.isDisposed()) {
\r
75 TableItem[] connectedVariables = allowedVariables.getItems();
\r
76 for(TableItem ti : connectedVariables) {
\r
77 // The status of the variable is determined using the color of its table item :(
\r
78 if (ExpressionUtils.variableTimeAndSelfColor(resourceManager).equals(ti.getForeground())) {
\r
79 this.timeAndSelfVariables.add(ti.getText());
\r
81 this.variables.add(ti.getText());
\r
86 Collections.sort(variables);
\r
87 Collections.sort(timeAndSelfVariables);
\r
92 * Create CompletionProposals of the variables and add them to array.
\r
93 * @param array result array of CompletionProposals
\r
94 * @param token current token
\r
95 * @param offset an offset within the document for which completions should be computed
\r
97 private void addVariables(ArrayList<ICompletionProposal> array, String token, int offset) {
\r
98 Image imageVariable = resourceManager.createImage(ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/variable.png")));
\r
99 Image imageVariableGray = resourceManager.createImage(ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/variableGray.png")));
\r
101 for (String variable : variables) {
\r
102 if (token.length() == 0 || variable.toUpperCase().startsWith(token.toUpperCase())) {
\r
103 array.add(new CompletionProposal(variable,
\r
104 offset - token.length(),
\r
106 variable.length(),
\r
113 for (String variable : timeAndSelfVariables) {
\r
114 if (token.length() == 0 || variable.toUpperCase().startsWith(token.toUpperCase())) {
\r
115 array.add(new CompletionProposal(variable,
\r
116 offset - token.length(),
\r
118 variable.length(),
\r
119 imageVariableGray,
\r
128 * Create CompletionProposals of the functions and add them to array.
\r
129 * @param array result array of CompletionProposals
\r
130 * @param token current token
\r
131 * @param offset an offset within the document for which completions should be computed
\r
133 private void addFunctions(ArrayList<ICompletionProposal> array, String token, int offset) {
\r
134 // Parameters don't have functions
\r
135 if (functions == null)
\r
138 // Create CompletionProposals out of Functions
\r
139 for (Function function : functions) {
\r
140 if (token.length() == 0 || function.getName().toUpperCase().startsWith(token.toUpperCase())) {
\r
141 Image image = Function.getImage(resourceManager, function);
\r
142 array.add(new CompletionProposal(
\r
143 function.getName() + "(" + function.getParameterList() + ")",
\r
144 offset - token.length(),
\r
146 function.getName().length() + 1,
\r
148 function.getName() + "(" + function.getParameterList() + ")",
\r
150 function.getDescriptionHTML()));
\r
156 * Collect all matching proposals
\r
157 * @param token current token
\r
158 * @param offset an offset within the document for which completions should be computed
\r
159 * @return Array of matching proposals
\r
161 private ICompletionProposal[] collectProposals(String token, int offset) {
\r
162 ArrayList<ICompletionProposal> resultArray = new ArrayList<ICompletionProposal>();
\r
164 // Find variables and functions and create CompletionProposals out of them.
\r
166 addVariables(resultArray, token, offset);
\r
167 addFunctions(resultArray, token, offset);
\r
169 ICompletionProposal[] result = new ICompletionProposal[resultArray.size()];
\r
170 for (int i = 0; i < result.length; ++i) {
\r
171 result[i] = resultArray.get(i);
\r
177 public ICompletionProposal[] computeCompletionProposals(
\r
178 ITextViewer viewer, int offset) {
\r
179 String equation = viewer.getDocument().get();
\r
180 Control control = viewer.getTextWidget();
\r
181 this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), control);
\r
183 if (equation.length() == 0
\r
185 || Character.isWhitespace(equation.charAt(offset - 1))) {
\r
186 return collectProposals("", offset);
\r
189 equation = equation.substring(0, offset);
\r
191 // Split into tokens on whitespace characters
\r
192 String[] tokens = equation.split("[\\s]");
\r
193 if (tokens.length == 0) {
\r
194 return collectProposals("", offset);
\r
196 String token = tokens[tokens.length - 1];
\r
198 // If a '+', '-', etc. character is in the end, return all.
\r
199 if (allowedConnectedCharactersRegExp.indexOf(token.charAt(token.length() - 1)) != -1) {
\r
200 return collectProposals("", offset);
\r
203 // Split the last token on '+', '-', etc. characters
\r
204 String tokensOfLastToken[] = token.split(allowedConnectedCharactersRegExp);
\r
205 if (tokensOfLastToken.length == 0) {
\r
206 return collectProposals("", offset);
\r
208 token = tokensOfLastToken[tokensOfLastToken.length - 1];
\r
209 //System.out.println(token + "\noffset = " + offset);
\r
211 return collectProposals(token, offset);
\r
215 public IContextInformation[] computeContextInformation(
\r
216 ITextViewer viewer, int offset) {
\r
221 public char[] getCompletionProposalAutoActivationCharacters() {
\r
222 return allowedCharacters;
\r
226 public char[] getContextInformationAutoActivationCharacters() {
\r
231 public String getErrorMessage() {
\r
232 return "Error in CompletionProcessor";
\r
236 public IContextInformationValidator getContextInformationValidator() {
\r