/******************************************************************************* * 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)); } }; } }