Java tutorial
/******************************************************************************* * Copyright (c) 2014 Bruno Medeiros and other Contributors. * All rights reserved. This program and the accompanying materials * are 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: * Bruno Medeiros - initial API and implementation *******************************************************************************/ package melnorme.lang.ide.ui.text; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.DefaultInformationControl; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.contentassist.ContentAssistant; import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.presentation.IPresentationReconciler; import org.eclipse.jface.text.presentation.PresentationReconciler; import org.eclipse.jface.text.rules.DefaultDamagerRepairer; import org.eclipse.jface.text.rules.Token; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; import melnorme.lang.ide.core.TextSettings_Actual; import melnorme.lang.ide.core.TextSettings_Actual.LangPartitionTypes; import melnorme.lang.ide.ui.CodeFormatterConstants; import melnorme.lang.ide.ui.EditorSettings_Actual; import melnorme.lang.ide.ui.LangUIMessages; import melnorme.lang.ide.ui.LangUIPlugin; import melnorme.lang.ide.ui.editor.ProjectionViewerExt; import melnorme.lang.ide.ui.editor.ViewerColorUpdater; import melnorme.lang.ide.ui.text.coloring.StylingPreferences; import melnorme.lang.ide.ui.text.coloring.TokenRegistry; import melnorme.util.swt.jface.text.ColorManager2; import melnorme.utilbox.collections.ArrayList2; import melnorme.utilbox.misc.ArrayUtil; import melnorme.utilbox.ownership.IDisposable; /** * Abstract SourceViewConfiguration * Has code to help manage the configured scanners, and let respond to preference changes. */ public abstract class AbstractLangBasicSourceViewerConfiguration extends TextSourceViewerConfiguration { protected final IPreferenceStore preferenceStore; protected final ColorManager2 colorManager; protected final StylingPreferences stylingPrefs; public AbstractLangBasicSourceViewerConfiguration(IPreferenceStore preferenceStore) { super(assertNotNull(preferenceStore)); this.preferenceStore = preferenceStore; this.colorManager = assertNotNull(init_ColorManager()); this.stylingPrefs = assertNotNull(init_StylePreferences()); } protected ColorManager2 init_ColorManager() { return LangUIPlugin.getInstance().getColorManager(); } protected StylingPreferences init_StylePreferences() { return EditorSettings_Actual.getStylingPreferences(); } protected final ColorManager2 getColorManager() { return colorManager; } public IPreferenceStore getPreferenceStore() { return preferenceStore; } public void handlePropertyChange(PropertyChangeEvent event, IPreferenceStore prefStore, SourceViewer sourceViewer) { assertTrue(prefStore == getPreferenceStore()); String property = event.getProperty(); updateIndentationSettings(sourceViewer, property); } /* ----------------- scanners / partitioning ----------------- */ @Override public String getConfiguredDocumentPartitioning(ISourceViewer sourceViewer) { return TextSettings_Actual.PARTITIONING_ID; } @Override public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) { return ArrayUtil.map(getPartitionTypes(), obj -> obj.getId(), String.class); } public LangPartitionTypes[] getPartitionTypes() { return TextSettings_Actual.LangPartitionTypes.values(); } @Override public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { PresentationReconciler reconciler = createPresentationReconciler(); reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer)); setupPresentationReconciler(reconciler, sourceViewer); return reconciler; } protected PresentationReconciler createPresentationReconciler() { return new PresentationReconciler(); } protected void setupPresentationReconciler(PresentationReconciler reconciler, ISourceViewer sourceViewer) { // Must be called from UI thread assertTrue(Display.getCurrent() != null); // Create a token registry for given sourceViewer TokenRegistry tokenRegistry = new TokenRegistry(colorManager, stylingPrefs) { @Override protected void handleTokenModified(Token token) { sourceViewer.invalidateTextPresentation(); } }; addConfigurationScopedOwned(sourceViewer, tokenRegistry); ArrayList2<AbstractLangScanner> scanners = new ArrayList2<>(); for (LangPartitionTypes partitionType : getPartitionTypes()) { String contentType = partitionType.getId(); AbstractLangScanner scanner = createScannerFor(Display.getCurrent(), partitionType, tokenRegistry); scanners.add(scanner); DefaultDamagerRepairer dr = getDamagerRepairer(scanner, contentType); reconciler.setDamager(dr, contentType); reconciler.setRepairer(dr, contentType); } } @SuppressWarnings("unused") protected DefaultDamagerRepairer getDamagerRepairer(AbstractLangScanner scanner, String contentType) { return new DefaultDamagerRepairer(scanner); } protected void addConfigurationScopedOwned(ISourceViewer sourceViewer, IDisposable tokenStore) { if (sourceViewer instanceof ProjectionViewerExt) { ProjectionViewerExt viewerExt = (ProjectionViewerExt) sourceViewer; viewerExt.addConfigurationOwned(tokenStore); } else { sourceViewer.getTextWidget().addDisposeListener(e -> tokenStore.dispose()); } } protected abstract AbstractLangScanner createScannerFor(Display current, LangPartitionTypes partitionType, TokenRegistry tokenStore); public String getFontPropertyPreferenceKey() { return JFaceResources.TEXT_FONT; } /* ----------------- TextViewer ----------------- */ @Override public int getTabWidth(ISourceViewer sourceViewer) { if (fPreferenceStore == null) return super.getTabWidth(sourceViewer); return fPreferenceStore.getInt(CodeFormatterConstants.FORMATTER_TAB_SIZE.key); } protected void updateIndentationSettings(SourceViewer sourceViewer, String property) { if (CodeFormatterConstants.FORMATTER_TAB_SIZE.key.equals(property)) { StyledText textWidget = sourceViewer.getTextWidget(); int tabWidth = getTabWidth(sourceViewer); textWidget.setTabs(tabWidth); } } /* ----------------- Presentation UI controls ----------------- */ @Override public IInformationControlCreator getInformationControlCreator(ISourceViewer sourceViewer) { return new IInformationControlCreator() { @Override public IInformationControl createInformationControl(Shell parent) { return new DefaultInformationControl(parent, false); } }; } protected IInformationControlCreator getInformationControl_ContentAsssist(final String statusFieldText) { return new IInformationControlCreator() { @Override public IInformationControl createInformationControl(Shell parent) { return new DefaultInformationControl(parent, statusFieldText); } }; } /* ----------------- ----------------- */ public static final String getAdditionalInfoAffordanceString() { IPreferenceStore store = EditorsUI.getPreferenceStore(); if (!store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE)) { return null; } return LangUIMessages.SourceHover_additionalInfo_affordance; } public static ContentAssistant setupSimpleContentAssistant(IContentAssistProcessor cap, String[] contentTypes) { ContentAssistant ca = new ContentAssistant(); ca.enableAutoActivation(true); ca.enableAutoInsert(true); for (String partitionType : contentTypes) { ca.setContentAssistProcessor(cap, partitionType); } return ca; } /* ----------------- ----------------- */ public void configureViewer(ProjectionViewerExt sourceViewer) { StyledText textWidget = sourceViewer.getTextWidget(); if (textWidget != null) { textWidget.setFont(JFaceResources.getFont(getFontPropertyPreferenceKey())); // TODO: respond to font changes } new ViewerColorUpdater(fPreferenceStore, sourceViewer).configureViewer(); } }