| /* |
| * Copyright (C) 2007 The Android Open Source Project |
| * |
| * Licensed under the Eclipse Public License, Version 1.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.eclipse.org/org/documents/epl-v10.php |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.ide.eclipse.adt.internal.editors; |
| |
| |
| import com.android.ide.eclipse.adt.internal.editors.formatting.AndroidXmlFormatter; |
| import com.android.ide.eclipse.adt.internal.editors.formatting.AndroidXmlFormattingStrategy; |
| |
| import org.eclipse.jface.text.DefaultAutoIndentStrategy; |
| import org.eclipse.jface.text.IAutoEditStrategy; |
| import org.eclipse.jface.text.ITextHover; |
| import org.eclipse.jface.text.ITextViewer; |
| import org.eclipse.jface.text.contentassist.ICompletionProposal; |
| import org.eclipse.jface.text.contentassist.IContentAssistProcessor; |
| import org.eclipse.jface.text.contentassist.IContentAssistant; |
| import org.eclipse.jface.text.contentassist.IContextInformation; |
| import org.eclipse.jface.text.contentassist.IContextInformationValidator; |
| import org.eclipse.jface.text.formatter.IContentFormatter; |
| import org.eclipse.jface.text.formatter.MultiPassContentFormatter; |
| import org.eclipse.jface.text.source.ISourceViewer; |
| import org.eclipse.wst.sse.core.text.IStructuredPartitions; |
| import org.eclipse.wst.xml.core.text.IXMLPartitions; |
| import org.eclipse.wst.xml.ui.StructuredTextViewerConfigurationXML; |
| import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentAssistProcessor; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * Base Source Viewer Configuration for Android resources. |
| */ |
| @SuppressWarnings({"restriction", "deprecation"}) // XMLContentAssistProcessor etc |
| public abstract class AndroidSourceViewerConfig extends StructuredTextViewerConfigurationXML { |
| |
| public AndroidSourceViewerConfig() { |
| super(); |
| } |
| |
| @Override |
| public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { |
| return super.getContentAssistant(sourceViewer); |
| } |
| |
| /** |
| * Returns the IContentAssistProcessor that |
| * {@link #getContentAssistProcessors(ISourceViewer, String)} should use |
| * for XML and default/unknown partitions. |
| * |
| * @return An {@link IContentAssistProcessor} or null. |
| */ |
| public abstract IContentAssistProcessor getAndroidContentAssistProcessor( |
| ISourceViewer sourceViewer, |
| String partitionType); |
| |
| /** |
| * Returns the content assist processors that will be used for content |
| * assist in the given source viewer and for the given partition type. |
| * |
| * @param sourceViewer the source viewer to be configured by this |
| * configuration |
| * @param partitionType the partition type for which the content assist |
| * processors are applicable |
| * @return IContentAssistProcessors or null if should not be supported |
| */ |
| @Override |
| protected IContentAssistProcessor[] getContentAssistProcessors( |
| ISourceViewer sourceViewer, String partitionType) { |
| ArrayList<IContentAssistProcessor> processors = new ArrayList<IContentAssistProcessor>(); |
| if (partitionType == IStructuredPartitions.UNKNOWN_PARTITION || |
| partitionType == IStructuredPartitions.DEFAULT_PARTITION || |
| partitionType == IXMLPartitions.XML_DEFAULT) { |
| |
| IContentAssistProcessor processor = |
| getAndroidContentAssistProcessor(sourceViewer, partitionType); |
| |
| if (processor != null) { |
| processors.add(processor); |
| } |
| } |
| |
| IContentAssistProcessor[] others = super.getContentAssistProcessors(sourceViewer, |
| partitionType); |
| if (others != null && others.length > 0) { |
| for (IContentAssistProcessor p : others) { |
| // Builtin Eclipse WTP code completion assistant? If so, |
| // wrap it with our own filter which hides some unwanted completions. |
| if (p instanceof XMLContentAssistProcessor |
| // On Eclipse 3.7, XMLContentAssistProcessor is no longer used, |
| // and instead org.eclipse.wst.xml.ui.internal.contentassist. |
| // XMLStructuredContentAssistProcessor is used - which isn't available |
| // at compile time in 3.5. |
| || p.getClass().getSimpleName().equals( |
| "XMLStructuredContentAssistProcessor")) { //$NON-NLS-1$ |
| processors.add(new FilteringContentAssistProcessor(p)); |
| } else { |
| processors.add(p); |
| } |
| } |
| } |
| |
| if (processors.size() > 0) { |
| return processors.toArray(new IContentAssistProcessor[processors.size()]); |
| } else { |
| return null; |
| } |
| } |
| |
| @Override |
| public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) { |
| // TODO text hover for android xml |
| return super.getTextHover(sourceViewer, contentType); |
| } |
| |
| @Override |
| public IAutoEditStrategy[] getAutoEditStrategies( |
| ISourceViewer sourceViewer, String contentType) { |
| IAutoEditStrategy[] strategies = super.getAutoEditStrategies(sourceViewer, contentType); |
| List<IAutoEditStrategy> s = new ArrayList<IAutoEditStrategy>(strategies.length + 1); |
| s.add(new AndroidXmlAutoEditStrategy()); |
| |
| // Add other registered strategies, except the builtin indentation strategy which is |
| // now handled by the above AndroidXmlAutoEditStrategy |
| for (IAutoEditStrategy strategy : strategies) { |
| if (strategy instanceof DefaultAutoIndentStrategy) { |
| continue; |
| } |
| s.add(strategy); |
| } |
| |
| return s.toArray(new IAutoEditStrategy[s.size()]); |
| } |
| |
| @Override |
| public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) { |
| IContentFormatter formatter = super.getContentFormatter(sourceViewer); |
| |
| if (formatter instanceof MultiPassContentFormatter) { |
| ((MultiPassContentFormatter) formatter).setMasterStrategy( |
| new AndroidXmlFormattingStrategy()); |
| return formatter; |
| } else { |
| return new AndroidXmlFormatter(); |
| } |
| } |
| |
| @Override |
| protected Map<String, ?> getHyperlinkDetectorTargets(final ISourceViewer sourceViewer) { |
| @SuppressWarnings("unchecked") |
| Map<String, ?> targets = super.getHyperlinkDetectorTargets(sourceViewer); |
| // If we want to look up more context in our HyperlinkDetector via the |
| // getAdapter method, we should place an IAdaptable object into the map here. |
| targets.put("com.android.ide.eclipse.xmlCode", null); //$NON-NLS-1$ |
| return targets; |
| } |
| |
| /** |
| * A delegating {@link IContentAssistProcessor} whose purpose is to filter out some |
| * default Eclipse XML completions which are distracting in Android XML files |
| */ |
| private static class FilteringContentAssistProcessor implements IContentAssistProcessor { |
| private IContentAssistProcessor mDelegate; |
| |
| public FilteringContentAssistProcessor(IContentAssistProcessor delegate) { |
| super(); |
| mDelegate = delegate; |
| } |
| |
| @Override |
| public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { |
| ICompletionProposal[] result = mDelegate.computeCompletionProposals(viewer, offset); |
| if (result == null) { |
| return null; |
| } |
| |
| List<ICompletionProposal> proposals = |
| new ArrayList<ICompletionProposal>(result.length); |
| for (ICompletionProposal proposal : result) { |
| String replacement = proposal.getDisplayString(); |
| if (replacement.charAt(0) == '"' && |
| replacement.charAt(replacement.length() - 1) == '"') { |
| // Filter out attribute values. In Android XML files (where there is no DTD |
| // etc) the default Eclipse XML code completion simply provides the |
| // existing value as a completion. This is often misleading, since if you |
| // for example have a typo, completion will show your current (wrong) |
| // value as a valid completion. |
| } else if (replacement.contains("Namespace") //$NON-NLS-1$ |
| || replacement.startsWith("XSL ") //$NON-NLS-1$ |
| || replacement.contains("Schema")) { //$NON-NLS-1$ |
| // Eclipse adds in a number of namespace and schema related completions which |
| // are not usually applicable in our files. |
| } else { |
| proposals.add(proposal); |
| } |
| } |
| |
| if (proposals.size() == result.length) { |
| return result; |
| } else { |
| return proposals.toArray(new ICompletionProposal[proposals.size()]); |
| } |
| } |
| |
| @Override |
| public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { |
| return mDelegate.computeContextInformation(viewer, offset); |
| } |
| |
| @Override |
| public char[] getCompletionProposalAutoActivationCharacters() { |
| return mDelegate.getCompletionProposalAutoActivationCharacters(); |
| } |
| |
| @Override |
| public char[] getContextInformationAutoActivationCharacters() { |
| return mDelegate.getContextInformationAutoActivationCharacters(); |
| } |
| |
| @Override |
| public IContextInformationValidator getContextInformationValidator() { |
| return mDelegate.getContextInformationValidator(); |
| } |
| |
| @Override |
| public String getErrorMessage() { |
| return mDelegate.getErrorMessage(); |
| } |
| } |
| } |