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