--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2012 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.browsing.ui.swt.contentassist;\r
+\r
+import java.util.Arrays;\r
+import java.util.Collection;\r
+import java.util.Map;\r
+import java.util.TreeMap;\r
+\r
+import org.eclipse.jface.fieldassist.IContentProposal;\r
+import org.eclipse.jface.fieldassist.IContentProposalListener;\r
+import org.eclipse.jface.fieldassist.TextContentAdapter;\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.FocusEvent;\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.KeyAdapter;\r
+import org.eclipse.swt.events.KeyEvent;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.events.TraverseEvent;\r
+import org.eclipse.swt.events.TraverseListener;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Text;\r
+\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ *\r
+ * @param <T>\r
+ */\r
+public class ContentAssistTextField extends Composite {\r
+\r
+ private static final boolean DEBUG = false;\r
+ \r
+ Text text;\r
+ INamedObject acceptedProposal;\r
+ INamedObject result;\r
+ OpenableContentAssistCommandAdapter contentAssist;\r
+\r
+ public <T extends INamedObject> ContentAssistTextField(final Composite parent, T initialValue, final T[] allowedValues, int style) {\r
+ this(parent, initialValue, Arrays.asList(allowedValues), style);\r
+ }\r
+\r
+ public <T extends INamedObject> ContentAssistTextField(final Composite parent, T initialValue, final Collection<T> allowedValues, int style) {\r
+ super(parent, style);\r
+ this.result = initialValue;\r
+\r
+ GridLayoutFactory.fillDefaults().applyTo(this);\r
+\r
+ text = new Text(this, style);\r
+ text.setText(initialValue == null ? "" : initialValue.getName());\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(text);\r
+\r
+ final Map<String, INamedObject> valueMap = new TreeMap<String, INamedObject>(String.CASE_INSENSITIVE_ORDER);\r
+ for (T t : allowedValues) {\r
+ valueMap.put(t.getName(), t);\r
+ }\r
+\r
+ contentAssist = new OpenableContentAssistCommandAdapter(text,\r
+ new TextContentAdapter(),\r
+ new NamedObjectContentProposalProvider<T>(allowedValues),\r
+ (String) null,\r
+ (char[]) null,\r
+ true\r
+ );\r
+ contentAssist.addContentProposalListener(new IContentProposalListener() {\r
+ @Override\r
+ public void proposalAccepted(IContentProposal proposal) {\r
+ if (DEBUG)\r
+ System.out.println("accepted: " + proposal);\r
+ acceptedProposal = ((INamedObjectContentProposal) proposal).getNamedObject();\r
+ ContentAssistTextField.this.result = acceptedProposal;\r
+ text.setText(acceptedProposal.getName());\r
+ text.setSelection(acceptedProposal.getName().length());\r
+ //text.selectAll();\r
+ }\r
+ });\r
+\r
+ text.addModifyListener(new ModifyListener() {\r
+ @Override\r
+ public void modifyText(ModifyEvent e) {\r
+ String t = text.getText();\r
+ if (DEBUG) {\r
+ System.out.println("text: " + t);\r
+ System.out.println("value set: " + valueMap);\r
+ }\r
+ INamedObject obj = valueMap.get(t);\r
+ if (obj == null) {\r
+ result = null;\r
+ if (DEBUG)\r
+ System.out.println("no result");\r
+ contentAssist.open();\r
+ } else {\r
+ result = obj;\r
+ if (DEBUG)\r
+ System.out.println("result: " + result);\r
+ }\r
+ }\r
+ });\r
+ text.addKeyListener(new KeyAdapter() {\r
+\r
+ @Override\r
+ public void keyPressed(KeyEvent e) {\r
+ if(e.keyCode == SWT.CR) {\r
+ String name = text.getText();\r
+ if (DEBUG)\r
+ System.out.println("CR: " + name);\r
+ if(name.isEmpty()) {\r
+ return;\r
+ }\r
+ if(acceptedProposal == null)\r
+ acceptedProposal = FindExactMatch.exec(name, allowedValues);\r
+ if(acceptedProposal == null)\r
+ contentAssist.open();\r
+ else {\r
+ ContentAssistTextField.this.result = acceptedProposal;\r
+ //text.setText(acceptedProposal.getName());\r
+ //text.traverse(SWT.TRAVERSE_TAB_NEXT);\r
+ //text.traverse(SWT.TRAVERSE_RETURN);\r
+ }\r
+ }\r
+ }\r
+\r
+ });\r
+ text.addFocusListener(new FocusListener() {\r
+\r
+ TraverseListener listener = new TraverseListener() {\r
+ @Override\r
+ public void keyTraversed(TraverseEvent e) {\r
+// System.out.println("CA TraverseListener PARENT TRAVERSE: " + e.detail);\r
+ if (e.detail == SWT.TRAVERSE_RETURN) {\r
+ e.doit = false;\r
+ }\r
+ }\r
+ };\r
+\r
+ @Override\r
+ public void focusLost(FocusEvent e) {\r
+ parent.removeTraverseListener(listener);\r
+ }\r
+\r
+ @Override\r
+ public void focusGained(FocusEvent e) {\r
+ parent.addTraverseListener(listener);\r
+ }\r
+ });\r
+\r
+ contentAssist.setPropagateKeys(true);\r
+ }\r
+\r
+ public INamedObject getResult() {\r
+ return result;\r
+ }\r
+\r
+ public Text getControl() {\r
+ return text;\r
+ }\r
+\r
+ public void openAssist() {\r
+ contentAssist.open();\r
+ }\r
+\r
+}\r