/*******************************************************************************
* Copyright (c) 2007-2011 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.text.xml;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.ITextHover;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
import org.eclipse.jface.text.information.IInformationProvider;
import org.eclipse.jface.text.quickassist.IQuickAssistAssistant;
import org.eclipse.jface.text.quickassist.QuickAssistAssistant;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration;
import org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext;
import org.eclipse.wst.sse.ui.internal.ExtendedConfigurationBuilder;
import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
import org.eclipse.wst.sse.ui.internal.derived.HTMLTextPresenter;
import org.eclipse.wst.sse.ui.internal.preferences.EditorPreferenceNames;
import org.eclipse.wst.sse.ui.internal.taginfo.AnnotationHoverProcessor;
import org.eclipse.wst.sse.ui.internal.taginfo.TextHoverManager;
import org.eclipse.wst.sse.ui.internal.util.EditorUtility;
import org.eclipse.wst.xml.ui.StructuredTextViewerConfigurationXML;
import org.eclipse.wst.xml.ui.internal.contentassist.XMLStructuredContentAssistProcessor;
import org.jboss.tools.common.text.xml.contentassist.ProposalSorter;
import org.jboss.tools.common.text.xml.info.ChainTextHover;
import org.jboss.tools.common.text.xml.xpl.MarkerProblemAnnotationHoverProcessor;
import org.jboss.tools.common.text.xml.info.TextHoverInformationProvider;
/**
* @author Igels
*/
@SuppressWarnings("restriction")
public class XMLTextViewerConfiguration extends StructuredTextViewerConfigurationXML {
private static final char[] PROPOSAL_AUTO_ACTIVATION_CHARS = new char[] {
'<', '=', '"', '\'', '.', '{', '['
};
SourceViewerConfiguration initial = null;
public XMLTextViewerConfiguration() {
super();
}
public void setInitialConfiguration(SourceViewerConfiguration initial) {
this.initial = initial;
}
protected IContentAssistProcessor[] getContentAssistProcessors(ISourceViewer sourceViewer, String partitionType) {
// IContentAssistProcessor[] superProcessors = super.getContentAssistProcessors(
// sourceViewer, partitionType);
IContentAssistProcessor superProcessor = new XMLStructuredContentAssistProcessor(
this.getContentAssistant(), partitionType, sourceViewer) {
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
protected List filterAndSortProposals(List proposals,
IProgressMonitor monitor,
CompletionProposalInvocationContext context) {
return ProposalSorter.filterAndSortProposals(proposals, monitor, context);
}
@Override
public char[] getCompletionProposalAutoActivationCharacters() {
char[] superAutoActivationCharacters = super.getCompletionProposalAutoActivationCharacters();
if (superAutoActivationCharacters == null)
return PROPOSAL_AUTO_ACTIVATION_CHARS;
String chars = new String(superAutoActivationCharacters);
for (char ch : PROPOSAL_AUTO_ACTIVATION_CHARS) {
if (chars.indexOf(ch) == -1) {
chars += ch;
}
}
return chars.toCharArray();
}
};
List<IContentAssistProcessor> processors = new ArrayList<IContentAssistProcessor>();
// SortingCompoundContentAssistProcessor sortingCompoundProcessor = new SortingCompoundContentAssistProcessor(sourceViewer, partitionType);
// if (sortingCompoundProcessor.supportsPartitionType(partitionType)) {
// processors.add(sortingCompoundProcessor);
// }
// processors.addAll(Arrays.asList(superProcessors));
processors.add(superProcessor);
return processors.toArray(new IContentAssistProcessor[0]);
}
/*
* @see org.eclipse.jface.text.source.SourceViewerConfiguration#getHyperlinkDetectors(org.eclipse.jface.text.source.ISourceViewer)
* @since 3.1
*/
public IHyperlinkDetector[] getHyperlinkDetectors(ISourceViewer sourceViewer) {
if (!fPreferenceStore.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_HYPERLINKS_ENABLED))
return null;
List<IHyperlinkDetector> allDetectors = new ArrayList<IHyperlinkDetector>(0);
IHyperlinkDetector extHyperlinkDetector = getTextEditorsExtensionsHyperlinkDetector();
if (extHyperlinkDetector != null) allDetectors.add(extHyperlinkDetector);
IHyperlinkDetector[] superDetectors = super.getHyperlinkDetectors(sourceViewer);
if (superDetectors != null) {
for (IHyperlinkDetector detector : superDetectors) {
if (!allDetectors.contains(detector)) {
allDetectors.add(detector);
}
}
}
return allDetectors.toArray(new IHyperlinkDetector[0]);
}
@SuppressWarnings("deprecation")
private IHyperlinkDetector getTextEditorsExtensionsHyperlinkDetector() {
Plugin plugin = Platform.getPlugin("org.jboss.tools.common.text.ext"); //$NON-NLS-1$
return (plugin != null && plugin instanceof IAdaptable ? (IHyperlinkDetector)((IAdaptable)plugin).getAdapter(IHyperlinkDetector.class):null);
}
/**
* @deprecated
*/
IContentAssistProcessor[] getInitialProcessors(ISourceViewer sourceViewer, String partitionType) {
if(initial == null) return null;
//method getContentAssistProcessors() is declared in StructuredTextViewerConfiguration
//and its subclasses
if(!(initial instanceof StructuredTextViewerConfiguration)) return null;
try {
Method m = findDeclaredMethod(initial.getClass(), "getContentAssistProcessors", new Class[]{ISourceViewer.class, String.class}); //$NON-NLS-1$
if(m == null) return null;
m.setAccessible(true);
return (IContentAssistProcessor[])m.invoke(initial, new Object[]{sourceViewer, partitionType});
} catch (IllegalArgumentException e) {
XmlEditorPlugin.getPluginLog().logError(e);
} catch (IllegalAccessException e) {
XmlEditorPlugin.getPluginLog().logError(e);
} catch (InvocationTargetException e) {
XmlEditorPlugin.getPluginLog().logError(e);
}
return null;
}
/**
* @deprecated
*/
@SuppressWarnings("rawtypes")
private Method findDeclaredMethod(Class cls, String name, Class[] paramTypes) {
Method[] ms = cls.getDeclaredMethods();
if (ms != null) for (int i = 0; i < ms.length; i++) {
if(!ms[i].getName().equals(name)) continue;
Class<?>[] ps = ms[i].getParameterTypes();
if(ps == null || ps.length != paramTypes.length) continue;
boolean equal = true;
for (int j = 0; j < ps.length && equal; j++) {
if(!ps[j].getName().equals(paramTypes[j].getName())) equal = false;
}
if(!equal) continue;
return ms[i];
}
Class<?> sc = cls.getSuperclass();
if(sc == null || sc == Object.class)
return null;
return findDeclaredMethod(sc, name, paramTypes);
}
/**
* Create documentation hovers based on hovers contributed via
* <code>org.eclipse.wst.sse.ui.editorConfiguration</code> extension point
*
* Copied from
* {@link org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration} because
* of private modifier
*
* @param partitionType
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private ITextHover[] createDocumentationHovers(String partitionType) {
List extendedTextHover = ExtendedConfigurationBuilder.getInstance()
.getConfigurations(
ExtendedConfigurationBuilder.DOCUMENTATIONTEXTHOVER,
partitionType);
return (ITextHover[]) extendedTextHover
.toArray(new ITextHover[extendedTextHover.size()]);
}
@Override
protected IInformationProvider getInformationProvider(
ISourceViewer sourceViewer, String partitionType) {
ITextHover[] hovers = createDocumentationHovers(partitionType);
return new TextHoverInformationProvider(new ChainTextHover(
hovers));
}
@Override
public ITextHover getTextHover(ISourceViewer sourceViewer,
String contentType, int stateMask) {
ITextHover textHover = null;
/*
* Returns a default problem, annotation, and best match hover depending
* on stateMask
*/
TextHoverManager.TextHoverDescriptor[] hoverDescs = SSEUIPlugin
.getDefault().getTextHoverManager().getTextHovers();
int i = 0;
while (i < hoverDescs.length && textHover == null) {
if (hoverDescs[i].isEnabled()
&& computeStateMask(hoverDescs[i].getModifierString()) == stateMask) {
String hoverType = hoverDescs[i].getId();
if (TextHoverManager.PROBLEM_HOVER.equalsIgnoreCase(hoverType))
// textHover = new ProblemAnnotationHoverProcessor();
textHover = new MarkerProblemAnnotationHoverProcessor();
else if (TextHoverManager.ANNOTATION_HOVER
.equalsIgnoreCase(hoverType))
textHover = new AnnotationHoverProcessor();
else if (TextHoverManager.COMBINATION_HOVER
.equalsIgnoreCase(hoverType)) {
textHover = new ChainTextHover(createDocumentationHovers(contentType));
} else if (TextHoverManager.DOCUMENTATION_HOVER
.equalsIgnoreCase(hoverType)) {
ITextHover[] hovers = createDocumentationHovers(contentType);
if (hovers.length > 0) {
textHover = hovers[0];
}
}
}
i++;
}
return textHover;
}
private IQuickAssistAssistant fQuickAssistant = null;
private Color getColor(String key) {
RGB rgb = PreferenceConverter.getColor(fPreferenceStore, key);
return EditorUtility.getColor(rgb);
}
@Override
public IQuickAssistAssistant getQuickAssistAssistant(ISourceViewer sourceViewer) {
if (fQuickAssistant == null) {
IQuickAssistAssistant assistant = new QuickAssistAssistant();
assistant.setQuickAssistProcessor(new BaseQuickAssistProcessor());
assistant.setInformationControlCreator(getQuickAssistAssistantInformationControlCreator());
if (fPreferenceStore != null) {
Color color = getColor(EditorPreferenceNames.CODEASSIST_PROPOSALS_BACKGROUND);
assistant.setProposalSelectorBackground(color);
color = getColor(EditorPreferenceNames.CODEASSIST_PROPOSALS_FOREGROUND);
assistant.setProposalSelectorForeground(color);
}
fQuickAssistant = assistant;
}
return fQuickAssistant;
}
/**
* Returns the information control creator for the quick assist assistant.
*
* @return the information control creator
*/
private IInformationControlCreator getQuickAssistAssistantInformationControlCreator() {
return new IInformationControlCreator() {
public IInformationControl createInformationControl(Shell parent) {
return new DefaultInformationControl(parent, new HTMLTextPresenter(true));
}
};
}
}