| /*=============================================================================# |
| # Copyright (c) 2005, 2021 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.ltk.ui.sourceediting; |
| |
| import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert; |
| |
| import static org.eclipse.statet.ltk.ui.LtkUI.BUNDLE_ID; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.jface.internal.text.html.BrowserInformationControl; |
| import org.eclipse.jface.internal.text.html.HTMLTextPresenter; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.text.AbstractInformationControlManager; |
| import org.eclipse.jface.text.AbstractReusableInformationControlCreator; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.DefaultInformationControl; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IInformationControl; |
| import org.eclipse.jface.text.IInformationControlCreator; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.ITextHover; |
| import org.eclipse.jface.text.ITextViewer; |
| import org.eclipse.jface.text.ITextViewerExtension2; |
| import org.eclipse.jface.text.contentassist.IContentAssistant; |
| import org.eclipse.jface.text.information.IInformationPresenter; |
| import org.eclipse.jface.text.information.IInformationProvider; |
| import org.eclipse.jface.text.information.IInformationProviderExtension2; |
| import org.eclipse.jface.text.information.InformationPresenter; |
| import org.eclipse.jface.text.presentation.IPresentationReconciler; |
| import org.eclipse.jface.text.presentation.PresentationReconciler; |
| import org.eclipse.jface.text.quickassist.IQuickAssistAssistant; |
| import org.eclipse.jface.text.quickassist.IQuickAssistProcessor; |
| import org.eclipse.jface.text.quickassist.QuickAssistAssistant; |
| import org.eclipse.jface.text.rules.DefaultDamagerRepairer; |
| import org.eclipse.jface.text.rules.ITokenScanner; |
| import org.eclipse.jface.text.source.ISourceViewer; |
| import org.eclipse.jface.text.templates.TemplateContextType; |
| import org.eclipse.jface.text.templates.TemplateVariableResolver; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.editors.text.EditorsUI; |
| import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; |
| import org.eclipse.ui.statushandlers.StatusManager; |
| |
| import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet; |
| |
| import org.eclipse.statet.ecommons.templates.TemplateVariableProcessor; |
| import org.eclipse.statet.ecommons.templates.WordFinder; |
| import org.eclipse.statet.ecommons.text.ICharPairMatcher; |
| import org.eclipse.statet.ecommons.text.IIndentSettings; |
| import org.eclipse.statet.ecommons.text.IndentUtil; |
| import org.eclipse.statet.ecommons.text.core.sections.DocContentSections; |
| import org.eclipse.statet.ecommons.text.ui.DefaultBrowserInformationInput; |
| import org.eclipse.statet.ecommons.text.ui.presentation.ITextPresentationConstants; |
| import org.eclipse.statet.ecommons.text.ui.presentation.TextStyleManager; |
| import org.eclipse.statet.ecommons.text.ui.settings.DecorationPreferences; |
| import org.eclipse.statet.ecommons.text.ui.settings.PreferenceStoreTextStyleManager; |
| import org.eclipse.statet.ecommons.ui.ISettingsChangedHandler; |
| import org.eclipse.statet.ecommons.ui.dialogs.DialogUtils; |
| import org.eclipse.statet.ecommons.ui.util.InformationDispatchHandler; |
| |
| import org.eclipse.statet.internal.ltk.ui.LtkUIPlugin; |
| import org.eclipse.statet.ltk.ui.LtkUIPreferences; |
| import org.eclipse.statet.ltk.ui.sourceediting.assist.AssistPreferences; |
| import org.eclipse.statet.ltk.ui.sourceediting.assist.ContentAssist; |
| import org.eclipse.statet.ltk.ui.sourceediting.assist.InfoHoverDescriptor; |
| import org.eclipse.statet.ltk.ui.sourceediting.assist.InfoHoverRegistry; |
| import org.eclipse.statet.ltk.ui.sourceediting.assist.InfoHoverRegistry.EffectiveHovers; |
| |
| |
| /** |
| * Abstract configuration for {@link SourceEditor}s. |
| */ |
| public abstract class SourceEditorViewerConfiguration extends TextSourceViewerConfiguration |
| implements ISettingsChangedHandler { |
| |
| |
| static final boolean DEBUG= true; |
| |
| |
| /** |
| * Flag to enable configuration for editing / showing templates. |
| * |
| * Overwrite: {@link #getTemplateVariableProcessor()} */ |
| public static final int TEMPLATE_MODE= 1 << 3; |
| |
| /** |
| * Flag to enable configuration for comparing sources. |
| */ |
| public static final int COMPARE_MODE= 1 << 4; |
| |
| |
| private static class AssistInformationControlCreator extends AbstractReusableInformationControlCreator { |
| |
| @Override |
| protected IInformationControl doCreateInformationControl(final Shell parent) { |
| if (BrowserInformationControl.isAvailable(parent)) { |
| return new BrowserInformationControl(parent, JFaceResources.DIALOG_FONT, false) { |
| |
| @Override |
| public void setInformation(final String content) { |
| if (content.startsWith("...<br")) { // spell correction change proposal //$NON-NLS-1$ |
| setInput(new DefaultBrowserInformationInput("", //$NON-NLS-1$ |
| content, DefaultBrowserInformationInput.FORMAT_HTMLSOURCE_INPUT )); |
| } |
| else { |
| setInput(new DefaultBrowserInformationInput("", //$NON-NLS-1$ |
| content, DefaultBrowserInformationInput.FORMAT_TEXT_INPUT )); |
| } |
| } |
| }; |
| } |
| else { |
| return new DefaultInformationControl(parent, new HTMLTextPresenter(false)); |
| } |
| } |
| |
| } |
| |
| |
| private static IInformationControlCreator assistTemplateInformationControlCreator; |
| |
| private static IInformationControlCreator assistDefaultInformationControlCreator; |
| |
| private static final IInformationControlCreator DEFAULT_INFORMATION_CONTROL_CREATOR= |
| new IInformationControlCreator() { |
| |
| @Override |
| public IInformationControl createInformationControl(final Shell parent) { |
| return new DefaultInformationControl(parent, true); |
| } |
| |
| }; |
| |
| private static final ITextHover NO_HOVER= new ITextHover() { |
| @Override |
| public IRegion getHoverRegion(final ITextViewer textViewer, final int offset) { |
| return null; |
| } |
| @Override |
| public String getHoverInfo(final ITextViewer textViewer, final IRegion hoverRegion) { |
| return null; |
| } |
| }; |
| |
| |
| private final DocContentSections documentContentInfo; |
| |
| private final int flags; |
| |
| private final SourceEditor editor; |
| |
| private PreferenceStoreTextStyleManager textStyles; |
| private final CopyOnWriteIdentityListSet<ISettingsChangedHandler> settingsHandler= new CopyOnWriteIdentityListSet<>(); |
| |
| private Map<String, ITokenScanner> scanners; |
| |
| private IPresentationReconciler presentationReconciler; |
| private ICharPairMatcher pairMatcher; |
| private ContentAssist contentAssistant; |
| private IQuickAssistAssistant quickAssistant; |
| |
| private DecorationPreferences decorationPreferences; |
| private AssistPreferences assistPreferences; |
| |
| private EffectiveHovers infoHovers; |
| private Map<Integer, ITextHover> infoHoverCache; |
| |
| |
| public SourceEditorViewerConfiguration(final DocContentSections documentContentInfo, final int flags, |
| final SourceEditor sourceEditor) { |
| if (documentContentInfo == null) { |
| throw new NullPointerException("documentContentInfo"); //$NON-NLS-1$ |
| } |
| this.documentContentInfo= documentContentInfo; |
| this.flags= flags; |
| this.editor= sourceEditor; |
| } |
| |
| |
| protected void setup(final IPreferenceStore preferenceStore, |
| final DecorationPreferences decoPrefs, final AssistPreferences assistPrefs) { |
| assert (preferenceStore != null); |
| this.fPreferenceStore= preferenceStore; |
| this.decorationPreferences= decoPrefs; |
| this.assistPreferences= assistPrefs; |
| } |
| |
| |
| public int getFlags() { |
| return this.flags; |
| } |
| |
| |
| protected void initTextStyles() { |
| } |
| |
| protected void setTextStyles(final PreferenceStoreTextStyleManager textStyles) { |
| this.textStyles= textStyles; |
| } |
| |
| protected TextStyleManager getTextStyles() { |
| if (this.textStyles == null) { |
| initTextStyles(); |
| } |
| return this.textStyles; |
| } |
| |
| |
| protected void initScanners() { |
| } |
| |
| protected void addScanner(final String contentType, final ITokenScanner scanner) { |
| this.scanners.put(contentType, scanner); |
| |
| if (scanner instanceof ISettingsChangedHandler) { |
| this.settingsHandler.add((ISettingsChangedHandler) scanner); |
| } |
| } |
| |
| protected ITokenScanner getScanner(final String contentType) { |
| if (this.scanners == null) { |
| this.scanners= new HashMap<>(); |
| initScanners(); |
| } |
| final ITokenScanner scanner= this.scanners.get(contentType); |
| if (DEBUG && scanner == null) { |
| StatusManager.getManager().handle(new Status(IStatus.WARNING, BUNDLE_ID, |
| "No scanner for contentType= " + contentType + "." )); |
| } |
| return scanner; |
| } |
| |
| |
| protected SourceEditor getSourceEditor() { |
| return this.editor; |
| } |
| |
| public final DocContentSections getDocumentContentInfo() { |
| return this.documentContentInfo; |
| } |
| |
| @Override |
| public final String getConfiguredDocumentPartitioning(final ISourceViewer sourceViewer) { |
| return this.documentContentInfo.getPartitioning(); |
| } |
| |
| public IPreferenceStore getPreferences() { |
| return this.fPreferenceStore; |
| } |
| |
| |
| public DecorationPreferences getDecorationPreferences() { |
| return this.decorationPreferences; |
| } |
| |
| public AssistPreferences getAssistPreferences() { |
| return this.assistPreferences; |
| } |
| |
| |
| @Override |
| public void handleSettingsChanged(final Set<String> groupIds, final Map<String, Object> options) { |
| if (this.assistPreferences != null |
| && (groupIds.contains(LtkUIPreferences.ASSIST_GROUP_ID) || groupIds.contains(this.assistPreferences.getGroupId())) ) { |
| if (this.contentAssistant != null) { |
| this.assistPreferences.configure(this.contentAssistant); |
| } |
| if (this.quickAssistant != null) { |
| this.assistPreferences.configure(this.quickAssistant); |
| } |
| } |
| if (this.textStyles != null && this.textStyles.affectsTextPresentation(groupIds)) { |
| options.put(ITextPresentationConstants.SETTINGSCHANGE_AFFECTSPRESENTATION_KEY, Boolean.TRUE); |
| } |
| for (final ISettingsChangedHandler handler : this.settingsHandler.toList()) { |
| handler.handleSettingsChanged(groupIds, options); |
| } |
| } |
| |
| @Override |
| public IPresentationReconciler getPresentationReconciler(final ISourceViewer sourceViewer) { |
| if (this.presentationReconciler == null) { |
| this.presentationReconciler= createPresentationReconciler(); |
| } |
| return this.presentationReconciler; |
| } |
| |
| protected IPresentationReconciler createPresentationReconciler() { |
| final PresentationReconciler reconciler= new PresentationReconciler(); |
| reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(null)); |
| |
| initPresentationReconciler(reconciler); |
| |
| return reconciler; |
| } |
| |
| PresentationReconciler getPresentationReconciler() { |
| return (PresentationReconciler) this.presentationReconciler; |
| } |
| |
| protected void initPresentationReconciler(final PresentationReconciler reconciler) { |
| final String[] contentTypes= getConfiguredContentTypes(null); |
| for (final String contentType : contentTypes) { |
| final ITokenScanner scanner= getScanner(contentType); |
| if (scanner != null) { |
| final DefaultDamagerRepairer dr= new DefaultDamagerRepairer(scanner); |
| reconciler.setDamager(dr, contentType); |
| reconciler.setRepairer(dr, contentType); |
| } |
| } |
| } |
| |
| |
| public List<SourceEditorAddon> getAddOns() { |
| return new ArrayList<>(); |
| } |
| |
| |
| public ICharPairMatcher getPairMatcher() { |
| if (this.pairMatcher == null) { |
| this.pairMatcher= createPairMatcher(); |
| } |
| return this.pairMatcher; |
| } |
| |
| protected ICharPairMatcher createPairMatcher() { |
| return null; |
| } |
| |
| |
| protected IIndentSettings getIndentSettings() { |
| return null; |
| } |
| |
| @Override |
| public int getTabWidth(final ISourceViewer sourceViewer) { |
| final IIndentSettings settings= getIndentSettings(); |
| if (settings != null) { |
| return settings.getTabSize(); |
| } |
| return super.getTabWidth(sourceViewer); |
| } |
| |
| @Override |
| public String[] getIndentPrefixes(final ISourceViewer sourceViewer, final String contentType) { |
| final IIndentSettings settings= getIndentSettings(); |
| if (settings != null) { |
| final String[] prefixes= getIndentPrefixesForTab(getTabWidth(sourceViewer)); |
| if (settings.getIndentDefaultType() == IIndentSettings.IndentationType.SPACES) { |
| for (int i= prefixes.length-2; i > 0; i--) { |
| prefixes[i]= prefixes[i-1]; |
| } |
| prefixes[0]= new String(IndentUtil.repeat(' ', settings.getIndentSpacesCount())); |
| } |
| return prefixes; |
| } |
| else { |
| return super.getIndentPrefixes(sourceViewer, contentType); |
| } |
| } |
| |
| |
| public boolean isSmartInsertSupported() { |
| return false; |
| } |
| |
| public boolean isSmartInsertByDefault() { |
| return true; |
| } |
| |
| |
| @Override |
| public IContentAssistant getContentAssistant(final ISourceViewer sourceViewer) { |
| if (this.contentAssistant == null) { |
| this.contentAssistant= ((getFlags() & TEMPLATE_MODE) != 0) ? |
| createTemplateVariableContentAssistant(sourceViewer) : |
| createContentAssistant(sourceViewer); |
| if (this.contentAssistant != null) { |
| if (this.assistPreferences != null) { |
| this.assistPreferences.configure(this.contentAssistant); |
| } |
| this.contentAssistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY); |
| this.contentAssistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE); |
| this.contentAssistant.setInformationControlCreator( |
| getAssistInformationControlCreator(sourceViewer) ); |
| } |
| } |
| return this.contentAssistant; |
| } |
| |
| public ContentAssist getContentAssist() { |
| return this.contentAssistant; |
| } |
| |
| protected ContentAssist createContentAssistant(final ISourceViewer sourceViewer) { |
| if (getSourceEditor() != null) { |
| final ContentAssist assistant= new ContentAssist(); |
| assistant.setDocumentPartitioning(getConfiguredDocumentPartitioning(null)); |
| assistant.setRestoreCompletionProposalSize(DialogUtils.getDialogSettings( |
| LtkUIPlugin.getInstance(), "ContentAssist.Proposal.size")); //$NON-NLS-1$ |
| |
| initContentAssist(assistant); |
| return assistant; |
| } |
| return null; |
| } |
| |
| protected void initContentAssist(final ContentAssist assistant) { |
| } |
| |
| |
| @Override |
| public IQuickAssistAssistant getQuickAssistAssistant(final ISourceViewer sourceViewer) { |
| if (this.quickAssistant == null) { |
| this.quickAssistant= createQuickAssistant(sourceViewer); |
| if (this.quickAssistant != null) { |
| if (this.assistPreferences != null) { |
| this.assistPreferences.configure(this.quickAssistant); |
| } |
| this.quickAssistant.setInformationControlCreator(getAssistInformationControlCreator(sourceViewer)); |
| } |
| } |
| return this.quickAssistant; |
| } |
| |
| protected IQuickAssistAssistant createQuickAssistant(final ISourceViewer sourceViewer) { |
| final IQuickAssistProcessor processor= createQuickAssistProcessor(); |
| if (processor != null) { |
| final QuickAssistAssistant assistant= new QuickAssistAssistant(); |
| assistant.setQuickAssistProcessor(processor); |
| assistant.enableColoredLabels(true); |
| assistant.setRestoreCompletionProposalSize(DialogUtils.getDialogSettings( |
| nonNullAssert(Platform.getBundle(EditorsUI.PLUGIN_ID)), |
| "quick_assist_proposal_size" )); //$NON-NLS-1$ |
| return assistant; |
| } |
| return super.getQuickAssistAssistant(sourceViewer); |
| } |
| |
| protected IQuickAssistProcessor createQuickAssistProcessor() { |
| return null; |
| } |
| |
| protected IInformationControlCreator getAssistInformationControlCreator(final ISourceViewer sourceViewer) { |
| if ((getFlags() & TEMPLATE_MODE) != 0) { |
| if (assistTemplateInformationControlCreator == null) { |
| assistTemplateInformationControlCreator= new IInformationControlCreator() { |
| @Override |
| public IInformationControl createInformationControl(final Shell parent) { |
| return new DefaultInformationControl(parent, |
| InformationDispatchHandler.getAdditionalInfoAffordanceString() ); |
| } |
| }; |
| } |
| return assistTemplateInformationControlCreator; |
| } |
| if (assistDefaultInformationControlCreator == null) { |
| assistDefaultInformationControlCreator= new AssistInformationControlCreator(); |
| } |
| return assistDefaultInformationControlCreator; |
| } |
| |
| @Override |
| public int[] getConfiguredTextHoverStateMasks(final ISourceViewer sourceViewer, final String contentType) { |
| if ((getFlags() & TEMPLATE_MODE) != 0) { |
| return new int[] { ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK }; |
| } |
| if (getSourceEditor() != null) { |
| return getInfoHoverStateMasks(contentType); |
| } |
| return super.getConfiguredTextHoverStateMasks(sourceViewer, contentType); |
| } |
| |
| @Override |
| public ITextHover getTextHover(final ISourceViewer sourceViewer, final String contentType) { |
| return getTextHover(sourceViewer, contentType, ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK); |
| } |
| |
| @Override |
| public ITextHover getTextHover(final ISourceViewer sourceViewer, final String contentType, final int stateMask) { |
| if ((getFlags() & TEMPLATE_MODE) != 0) { |
| return getTemplateVariableTextHover(sourceViewer); |
| } |
| return getInfoHover(sourceViewer, contentType, stateMask); |
| } |
| |
| |
| protected int[] getInfoHoverStateMasks(final String contentType) { |
| final String[] contentTypes= getConfiguredContentTypes(null); |
| if (contentTypes != null && contentTypes.length > 0 && contentTypes[0].equals(contentType)) { |
| initInfoHovers(); |
| } |
| if (this.infoHovers != null && isInfoHoverDefaultContentType(contentType)) { |
| return this.infoHovers.getStateMasks(); |
| } |
| return new int[] { ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK }; |
| } |
| |
| protected void initInfoHovers() { |
| final InfoHoverRegistry registry= getInfoHoverRegistry(); |
| this.infoHovers= (registry != null) ? registry.getEffectiveHoverDescriptors() : null; |
| if (this.infoHoverCache == null) { |
| this.infoHoverCache= new HashMap<>(); |
| } |
| else { |
| this.infoHoverCache.clear(); |
| } |
| } |
| |
| public EffectiveHovers getConfiguredInfoHovers() { |
| return this.infoHovers; |
| } |
| |
| protected ITextHover getInfoHover(final ISourceViewer sourceViewer, final String contentType, final int stateMask) { |
| if (this.infoHovers != null && isInfoHoverDefaultContentType(contentType)) { |
| final Integer key= Integer.valueOf(stateMask); |
| ITextHover hover= this.infoHoverCache.get(key); |
| if (hover == null) { |
| final InfoHoverDescriptor descriptor= this.infoHovers.getDescriptor(stateMask); |
| if (descriptor != null) { |
| hover= createInfoHover(descriptor); |
| if (hover == null) { |
| hover= NO_HOVER; |
| } |
| this.infoHoverCache.put(key, hover); |
| } |
| } |
| return (hover != NO_HOVER) ? hover : null; |
| } |
| return null; |
| } |
| |
| protected boolean isInfoHoverDefaultContentType(final String contentType) { |
| final String[] partitioning= getConfiguredContentTypes(null); |
| return (partitioning != null && partitioning.length > 0 && partitioning[0].equals(contentType)); |
| } |
| |
| protected InfoHoverRegistry getInfoHoverRegistry() { |
| return null; |
| } |
| |
| protected ITextHover createInfoHover(final InfoHoverDescriptor descriptor) { |
| return null; |
| } |
| |
| |
| @Override |
| public IInformationPresenter getInformationPresenter(final ISourceViewer sourceViewer) { |
| final InformationPresenter presenter= new InformationPresenter( |
| DEFAULT_INFORMATION_CONTROL_CREATOR); |
| presenter.setDocumentPartitioning(getConfiguredDocumentPartitioning(null)); |
| |
| // Register information provider |
| final IInformationProvider provider= getInformationProvider(); |
| final String[] contentTypes= getConfiguredContentTypes(null); |
| for (int i= 0; i < contentTypes.length; i++) { |
| presenter.setInformationProvider(provider, contentTypes[i]); |
| } |
| // sizes: see org.eclipse.jface.text.TextViewer.TEXT_HOVER_*_CHARS |
| presenter.setSizeConstraints(100, 12, true, true); |
| return presenter; |
| } |
| |
| protected IInformationProvider getInformationProvider() { |
| return null; |
| } |
| |
| |
| @Override |
| protected Map getHyperlinkDetectorTargets(final ISourceViewer sourceViewer) { |
| final Map<String, IAdaptable> targets= super.getHyperlinkDetectorTargets(sourceViewer); |
| collectHyperlinkDetectorTargets(targets, sourceViewer); |
| return targets; |
| } |
| |
| protected void collectHyperlinkDetectorTargets(final Map<String, IAdaptable> targets, final ISourceViewer sourceViewer) { |
| } |
| |
| public IInformationPresenter getQuickPresenter(final ISourceViewer sourceViewer, |
| final int operation) { |
| final IInformationProvider provider= getQuickInformationProvider(sourceViewer, operation); |
| if (provider == null) { |
| return null; |
| } |
| final InformationPresenter presenter= new InformationPresenter(((IInformationProviderExtension2) provider).getInformationPresenterControlCreator()); |
| presenter.setDocumentPartitioning(getConfiguredDocumentPartitioning(null)); |
| presenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL); |
| presenter.setSizeConstraints(50, 20, true, false); |
| |
| final String[] contentTypes= getConfiguredContentTypes(null); |
| for (int i= 0; i < contentTypes.length; i++) { |
| presenter.setInformationProvider(provider, contentTypes[i]); |
| } |
| |
| return presenter; |
| } |
| |
| protected IInformationProvider getQuickInformationProvider(final ISourceViewer sourceViewer, |
| final int operation) { |
| return null; |
| } |
| |
| |
| |
| /* For TemplateEditors ********************************************************/ |
| |
| protected TemplateVariableProcessor getTemplateVariableProcessor() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| protected ContentAssist createTemplateVariableContentAssistant(final ISourceViewer sourceViewer) { |
| final ContentAssist assistant= new ContentAssist(); |
| assistant.setDocumentPartitioning(getConfiguredDocumentPartitioning(null)); |
| |
| for (final String contentType : getConfiguredContentTypes(null)) { |
| assistant.setContentAssistProcessor(getTemplateVariableProcessor(), contentType); |
| } |
| |
| return assistant; |
| } |
| |
| protected static class TemplateVariableTextHover implements ITextHover { |
| |
| private final TemplateVariableProcessor processor; |
| |
| /** |
| * @param processor the template variable processor |
| */ |
| public TemplateVariableTextHover(final TemplateVariableProcessor processor) { |
| this.processor= processor; |
| } |
| |
| @Override |
| public String getHoverInfo(final ITextViewer textViewer, final IRegion subject) { |
| try { |
| final IDocument doc= textViewer.getDocument(); |
| final int offset= subject.getOffset(); |
| if (offset >= 2 && "${".equals(doc.get(offset-2, 2))) { //$NON-NLS-1$ |
| final String varName= doc.get(offset, subject.getLength()); |
| final TemplateContextType contextType= this.processor.getContextType(); |
| if (contextType != null) { |
| final Iterator iter= contextType.resolvers(); |
| while (iter.hasNext()) { |
| final TemplateVariableResolver var= (TemplateVariableResolver) iter.next(); |
| if (varName.equals(var.getType())) { |
| return var.getDescription(); |
| } |
| } |
| } |
| } |
| } catch (final BadLocationException e) { |
| } |
| return null; |
| } |
| |
| @Override |
| public IRegion getHoverRegion(final ITextViewer textViewer, final int offset) { |
| if (textViewer != null) { |
| return WordFinder.findWord(textViewer.getDocument(), offset); |
| } |
| return null; |
| } |
| |
| } |
| |
| public ITextHover getTemplateVariableTextHover(final ISourceViewer sourceViewer) { |
| final Integer key= Integer.valueOf(0); |
| ITextHover hover; |
| if (this.infoHoverCache != null) { |
| hover= this.infoHoverCache.get(key); |
| } |
| else { |
| hover= new TemplateVariableTextHover(getTemplateVariableProcessor()); |
| this.infoHoverCache= Collections.singletonMap(key, hover); |
| } |
| return hover; |
| } |
| |
| } |