package org.eclipse.uml2.diagram.parser.assist; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.contentassist.IContentAssistSubjectControl; import org.eclipse.jface.text.contentassist.CompletionProposal; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.uml2.diagram.parser.lookup.Lookup; import org.eclipse.uml2.uml.NamedElement; public abstract class LookupCompletionProcessor<T extends NamedElement> extends CompletionProcessorBase { protected static final Comparator<NamedElement> BY_NAME_COMPARATOR = new Comparator<NamedElement>() { public int compare(NamedElement first, NamedElement second) { return first.getName().compareTo(second.getName()); } }; private final Lookup<T> myLookup; private final ILabelProvider myProposalsLabelProvider; /** * Extracts the part of the control text related to the proposal. * <p> * E.g, if the complete text entered in control is "myName : Str", then the * type-proposal is expected to extract the proposal prefix "Str", because * everything before the ":" are not relevant for type proposals. * <p> * Only the proposals starting with this proposal prefix ("Str") will be * considered. * * @param prefix * text entered into the control before the actual selection * @return relevant part of the entered text, or <code>null</code> if given * text is not relevant to proposals at all (no assistant will be * shown in this case). */ protected abstract String getProposalPrefix(String controlPrefix); public LookupCompletionProcessor(Lookup<T> lookup, ILabelProvider proposalsLabelProvider) { myLookup = lookup; myProposalsLabelProvider = proposalsLabelProvider; } public ICompletionProposal[] computeCompletionProposals(IContentAssistSubjectControl subjectControl, int offset) { if (getContext() == null) { return NO_PROPOSALS; } String prefix = getControlTextBeforeSelection(subjectControl); String proposalPrefix = getProposalPrefix(prefix); if (proposalPrefix == null) { return NO_PROPOSALS; } List<T> proposedEObjects = computeLookupProposals(getContext()); List<ICompletionProposal> proposals = createProposals(subjectControl.getSelectedRange(), proposalPrefix, proposedEObjects); return proposals.toArray(NO_PROPOSALS); } protected List<T> computeLookupProposals(EObject context) { List<T> resultList = myLookup.computeScope(context); Collections.sort(resultList, BY_NAME_COMPARATOR); return resultList; } protected List<ICompletionProposal> createProposals(Point selection, String proposalPrefix, List<T> proposals) { String ignoreCasePrefix = proposalPrefix.toLowerCase(); int prefixLength = proposalPrefix.length(); int selectionStart = selection.x; int selectionLength = selection.y; List<ICompletionProposal> result = new ArrayList<ICompletionProposal>(proposals.size()); for (T next : proposals) { if (next == null) { continue; } String nextName = next.getName(); if (nextName == null || !nextName.toLowerCase().startsWith(ignoreCasePrefix)) { continue; } Image image = getProposalImage(next); ICompletionProposal proposal = new CompletionProposal(// nextName, selectionStart - prefixLength, selectionLength + prefixLength, nextName.length(), image, nextName, null, null); result.add(proposal); } return result; } protected Image getProposalImage(T proposedEObject) { return myProposalsLabelProvider == null ? null : myProposalsLabelProvider.getImage(proposedEObject); } protected static final String trimLeft(String text) { return text.startsWith(" ") ? text.replaceAll("\\A\\s+", "") : text; } }