diff --git a/bundles/org.eclipse.ui.editors/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui.editors/META-INF/MANIFEST.MF index 9a63a5630ff..2198f70e669 100644 --- a/bundles/org.eclipse.ui.editors/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.ui.editors/META-INF/MANIFEST.MF @@ -15,7 +15,8 @@ Export-Package: org.eclipse.ui.internal.editors.text.codemining.annotation;x-internal:=true, org.eclipse.ui.internal.texteditor;x-internal:=true, org.eclipse.ui.internal.texteditor.stickyscroll;x-internal:=true, - org.eclipse.ui.texteditor + org.eclipse.ui.texteditor, + org.eclipse.ui.texteditor.stickyscroll Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.29.0,4.0.0)", org.eclipse.core.expressions;bundle-version="[3.9.0,4.0.0)", diff --git a/bundles/org.eclipse.ui.editors/plugin.properties b/bundles/org.eclipse.ui.editors/plugin.properties index 777af9dbb87..f43d57fe4fc 100644 --- a/bundles/org.eclipse.ui.editors/plugin.properties +++ b/bundles/org.eclipse.ui.editors/plugin.properties @@ -20,6 +20,7 @@ ExtPoint.documentProviders= Document Provider ExtPoint.markerAnnotationSpecification= Marker Annotation Specification ExtPoint.annotationTypes= Annotation Types ExtPoint.editorTemplate= Editor Template +ExtPoint.stickyLinesProviders= Sticky Lines Provider convertDelimiters.Windows.name= Convert Line Delimiters to Windows (CRLF, \\r\\n, 0D0A, \u00A4\u00B6) convertDelimiters.Windows.label= &Windows (CRLF, \\r\\n, 0D0A, \u00A4\u00B6) diff --git a/bundles/org.eclipse.ui.editors/plugin.xml b/bundles/org.eclipse.ui.editors/plugin.xml index ce60714504a..c5f4a6e342d 100644 --- a/bundles/org.eclipse.ui.editors/plugin.xml +++ b/bundles/org.eclipse.ui.editors/plugin.xml @@ -20,6 +20,7 @@ + diff --git a/bundles/org.eclipse.ui.editors/schema/stickyLinesProviders.exsd b/bundles/org.eclipse.ui.editors/schema/stickyLinesProviders.exsd new file mode 100644 index 00000000000..e4aff87ed9a --- /dev/null +++ b/bundles/org.eclipse.ui.editors/schema/stickyLinesProviders.exsd @@ -0,0 +1,165 @@ + + + + + + + + + This extension point is used to register sticky lines providers for editors. + + + + + + + + + + + + + + + + + + + a fully qualified identifier of the target extension point + + + + + + + an optional identifier of the extension instance + + + + + + + an optional name of the extension instance + + + + + + + + + + + + + A sticky lines provider. + + + + + + + + + + A string uniquely identifying this sticky line provider + + + + + + + The fully qualified class name implementing the interface <code>org.eclipse.ui.texteditor.stickyscroll.IStickyLinesProvider</code>. + + + + + + + + + + + + + A core Expression that controls the enabled of the given sticky lines provider + + + + + + + + + + + + + + + + + + + + + + + + + + + 3.20 + + + + + + + + + The following is an example of a sticky line provider definition: +<pre> + <extension + point="org.eclipse.ui.editors.stickyLinesProviders"> + <stickyLinesProvider + class="org.eclipse.ui.internal.texteditor.stickyscroll.DefaultStickyLinesProvider" + id="org.eclipse.ui.editors.stickyLinesProviderExample" + label="Example sticky lines provider registration"> + <enabledWhen> + <and> + <with variable="editor"> + <instanceof value="org.example.MyEditorWithStickyScrolling"/> + </with> + </and> + </enabledWhen> + </stickyLinesProvider> + </extension> +</pre> + + + + + + + + + See the org.eclipse.ui.texteditor.stickyscroll.IStickyLinesProvider interface and the org.eclipse.ui.editors.stickyLinesProviders extension point. As default implementation for the IStickyLine, see org.eclipse.ui.texteditor.stickyscroll.StickyLine. + + + + + + + + + + Copyright (c) 2024 SAP SE.<br> +This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at <a href="https://www.eclipse.org/legal/epl-2.0">https://www.eclipse.org/legal/epl-v20.html</a>/ +SPDX-License-Identifier: EPL-2.0 +Contributors: + SAP SE - initial API and implementation + + + + diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/DefaultStickyLinesProvider.java b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/DefaultStickyLinesProvider.java index 40c3125f1af..367dbd0a98f 100644 --- a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/DefaultStickyLinesProvider.java +++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/DefaultStickyLinesProvider.java @@ -22,6 +22,10 @@ import org.eclipse.jface.text.ITextViewerExtension5; import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.ui.texteditor.stickyscroll.IStickyLine; +import org.eclipse.ui.texteditor.stickyscroll.IStickyLinesProvider; +import org.eclipse.ui.texteditor.stickyscroll.StickyLine; + /** * This class provides sticky lines for the given source code in the source viewer. The * implementation is completely based on indentation and therefore works by default for several diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLinesProviderDescriptor.java b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLinesProviderDescriptor.java new file mode 100644 index 00000000000..fd5ef49a455 --- /dev/null +++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLinesProviderDescriptor.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * Copyright (c) 2024 SAP SE. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * SAP SE - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.texteditor.stickyscroll; + +import org.eclipse.core.expressions.ElementHandler; +import org.eclipse.core.expressions.EvaluationContext; +import org.eclipse.core.expressions.EvaluationResult; +import org.eclipse.core.expressions.Expression; +import org.eclipse.core.expressions.ExpressionConverter; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +import org.eclipse.jface.text.source.ISourceViewer; + +import org.eclipse.ui.internal.editors.text.EditorsPlugin; + +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.stickyscroll.IStickyLinesProvider; + +import org.eclipse.ui.editors.text.EditorsUI; + +/** + * Describes an extension to the stickyLinesProviders extension point. + * + * @noextend This class is not intended to be extended by clients. + */ +class StickyLinesProviderDescriptor { + /** Name of the class attribute. */ + private static final String CLASS_ATTRIBUTE= "class"; //$NON-NLS-1$ + + /** Name of the id attribute. */ + private static final String ID_ATTRIBUTE= "id"; //$NON-NLS-1$ + + /** Name of the enabledWhen attribute. **/ + private static final String ENABLED_WHEN_ATTR= "enabledWhen"; //$NON-NLS-1$ + + /** The configuration element describing this extension. */ + private IConfigurationElement configuration; + + /** The value of the id attribute, if read. */ + private String id; + + /** The expression value of the enabledWhen attribute. */ + private final Expression enabledWhen; + + /** + * Creates a new descriptor for element. + *

+ * This method is for internal use only. + *

+ * + * @param element the extension point element to be described. + * @throws CoreException when enabledWhen expression is not valid. + */ + public StickyLinesProviderDescriptor(IConfigurationElement element) throws CoreException { + Assert.isLegal(element != null); + configuration= element; + enabledWhen= createEnabledWhen(configuration, getId()); + } + + /** + * Returns the expression {@link Expression} declared in the enabledWhen element. + * + * @param configElement the configuration element + * @param id the id of the sticky lines provider. + * @return the expression {@link Expression} declared in the enabledWhen element. + * @throws CoreException when enabledWhen expression is not valid. + */ + private static Expression createEnabledWhen(IConfigurationElement configElement, String id) throws CoreException { + final IConfigurationElement[] children= configElement.getChildren(ENABLED_WHEN_ATTR); + if (children.length > 0) { + IConfigurationElement[] subChildren= children[0].getChildren(); + if (subChildren.length != 1) { + throw new CoreException(new Status(IStatus.ERROR, EditorsUI.PLUGIN_ID, + "One element is accepted. Disabling " + id)); //$NON-NLS-1$ + } + final ElementHandler elementHandler= ElementHandler.getDefault(); + final ExpressionConverter converter= ExpressionConverter.getDefault(); + return elementHandler.create(converter, subChildren[0]); + } + return null; + } + + /** + * Reads (if needed) and returns the id of this extension. + * + * @return the id for this extension. + */ + public String getId() { + if (id == null) { + id= configuration.getAttribute(ID_ATTRIBUTE); + Assert.isNotNull(id); + } + return id; + } + + /** + * Creates a sticky lines provider as described in the extension's XML and null otherwise. + * + * @return the created sticky lines provider and null otherwise. + */ + protected IStickyLinesProvider createStickyLinesProvider() { + try { + Object extension= configuration.createExecutableExtension(CLASS_ATTRIBUTE); + if (extension instanceof IStickyLinesProvider stickyLinesProvider) { + return stickyLinesProvider; + } else { + String message= "Invalid extension to stickyLinesProvider. Must extends IStickyLinesProvider: " //$NON-NLS-1$ + + getId(); + EditorsPlugin.getDefault().getLog() + .log(new Status(IStatus.ERROR, EditorsUI.PLUGIN_ID, message)); + return null; + } + } catch (CoreException e) { + EditorsPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, EditorsUI.PLUGIN_ID, + "Error while creating stickyLinesProvider: " + getId(), e)); //$NON-NLS-1$ + return null; + } + } + + /** + * Returns true if the given viewer, editor matches the enabledWhen expression and false + * otherwise. + * + * @param viewer the viewer + * @param editor the editor + * @return true if the given viewer, editor matches the enabledWhen expression and false + * otherwise. + */ + public boolean matches(ISourceViewer viewer, ITextEditor editor) { + if (enabledWhen == null) { + return true; + } + EvaluationContext context= new EvaluationContext(null, editor); + context.setAllowPluginActivation(true); + context.addVariable("viewer", viewer); //$NON-NLS-1$ + context.addVariable("editor", editor); //$NON-NLS-1$ + context.addVariable("editorInput", editor.getEditorInput()); //$NON-NLS-1$ + try { + return enabledWhen.evaluate(context) == EvaluationResult.TRUE; + } catch (CoreException e) { + EditorsPlugin.getDefault().getLog().log( + new Status(IStatus.ERROR, EditorsUI.PLUGIN_ID, "Error while 'enabledWhen' evaluation", e)); //$NON-NLS-1$ + return false; + } + } +} diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLinesProviderRegistry.java b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLinesProviderRegistry.java new file mode 100644 index 00000000000..fdf111a9ec3 --- /dev/null +++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLinesProviderRegistry.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * Copyright (c) 2024 SAP SE. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * SAP SE - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.texteditor.stickyscroll; + +import static org.eclipse.ui.editors.text.EditorsUI.PLUGIN_ID; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; + +import org.eclipse.jface.text.source.ISourceViewer; + +import org.eclipse.ui.internal.editors.text.EditorsPlugin; + +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.stickyscroll.IStickyLinesProvider; + +/** + * Registry to read sticky lines provider from corresponding extension point. + */ +public class StickyLinesProviderRegistry { + /** + * Extension point id (value "stickyLinesProviders"). + */ + public static final String STICKY_LINES_PROVIDERS_EXTENSION_POINT = "stickyLinesProviders"; //$NON-NLS-1$ + + /** All descriptors */ + private StickyLinesProviderDescriptor[] fDescriptors; + + /** true if the extensions have been loaded at least once */ + private boolean fLoaded = false; + + private IExtensionRegistry fExtensionRegistry; + + private StickyLinesProviderDescriptorFactory descriptorFactory; + + public StickyLinesProviderRegistry() { + this(Platform.getExtensionRegistry(), element -> new StickyLinesProviderDescriptor(element)); + } + + public StickyLinesProviderRegistry(IExtensionRegistry extensionRegistry, + StickyLinesProviderDescriptorFactory StickyLinesProviderDescriptorFactory) { + fExtensionRegistry = extensionRegistry; + this.descriptorFactory = StickyLinesProviderDescriptorFactory; + } + + /** + * Returns the sticky lines providers for the given viewer and editor. If no + * specific provider is registered, a {@link DefaultStickyLinesProvider} is + * returned. + * + * @param viewer the viewer + * @param editor the editor + * @return the sticky lines providers for the given viewer and editor and a + * default provider otherwise. + */ + public IStickyLinesProvider getProvider(ISourceViewer viewer, ITextEditor editor) { + for (StickyLinesProviderDescriptor descriptor : getDescriptors()) { + if (descriptor.matches(viewer, editor)) { + IStickyLinesProvider provider = descriptor.createStickyLinesProvider(); + if (provider != null) { + return provider; + } + } + } + return new DefaultStickyLinesProvider(); + } + + /** + * Returns all descriptors. + * + * @return all descriptors + */ + private StickyLinesProviderDescriptor[] getDescriptors() { + ensureExtensionsLoaded(); + return fDescriptors; + } + + /** + * Reads all extensions. + *

+ * This method can be called more than once in order to reload from a changed + * extension registry. + *

+ */ + public synchronized void reloadExtensions() { + List descriptors = new ArrayList<>(); + IConfigurationElement[] elements = fExtensionRegistry.getConfigurationElementsFor(PLUGIN_ID, + STICKY_LINES_PROVIDERS_EXTENSION_POINT); + for (IConfigurationElement element : elements) { + try { + StickyLinesProviderDescriptor descriptor = descriptorFactory.create(element); + descriptors.add(descriptor); + } catch (CoreException e) { + EditorsPlugin.getDefault().getLog() + .log(new Status(IStatus.ERROR, element.getNamespaceIdentifier(), e.getMessage())); + } + } + fDescriptors = descriptors.toArray(StickyLinesProviderDescriptor[]::new); + fLoaded = true; + } + + /** + * Ensures the extensions have been loaded at least once. + */ + private void ensureExtensionsLoaded() { + if (!fLoaded) + reloadExtensions(); + } + + interface StickyLinesProviderDescriptorFactory { + public StickyLinesProviderDescriptor create(IConfigurationElement element) throws CoreException; + } +} diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControl.java b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControl.java index 7375afadfc4..99417df401d 100644 --- a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControl.java +++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControl.java @@ -60,10 +60,12 @@ import org.eclipse.ui.internal.texteditor.LineNumberColumn; +import org.eclipse.ui.texteditor.stickyscroll.IStickyLine; + /** * This class builds a control that is rendered on top of the given source viewer. The controls * shows the sticky lines that are set via {@link #setStickyLines(List)} on top of the source - * viewer. The {@link StickyLine#getLineNumber()} is linked to to corresponding line number in the + * viewer. The {@link IStickyLine#getLineNumber()} is linked to to corresponding line number in the * given source viewer, with index starting at 0. * * As part of its responsibilities, the class handles layout arrangement and styling of the sticky diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingHandler.java b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingHandler.java index de457cf0ca0..5ac5f2df526 100644 --- a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingHandler.java +++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingHandler.java @@ -38,8 +38,12 @@ import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.ui.IEditorPart; import org.eclipse.ui.internal.editors.text.EditorsPlugin; -import org.eclipse.ui.internal.texteditor.stickyscroll.IStickyLinesProvider.StickyLinesProperties; + +import org.eclipse.ui.texteditor.stickyscroll.IStickyLine; +import org.eclipse.ui.texteditor.stickyscroll.IStickyLinesProvider; +import org.eclipse.ui.texteditor.stickyscroll.IStickyLinesProvider.StickyLinesProperties; /** * A sticky scrolling handler that retrieves stick lines from a {@link IStickyLinesProvider} and @@ -65,17 +69,7 @@ public class StickyScrollingHandler implements IViewportListener { private int verticalOffset; - /** - * Creates a StickyScrollingHandler that will be linked to the given source viewer. The sticky - * lines will be provided by the {@link DefaultStickyLinesProvider}. - * - * @param sourceViewer The source viewer to link the handler with - * @param verticalRuler The vertical ruler of the source viewer - * @param preferenceStore The preference store - */ - public StickyScrollingHandler(ISourceViewer sourceViewer, IVerticalRuler verticalRuler, IPreferenceStore preferenceStore) { - this(sourceViewer, verticalRuler, preferenceStore, new DefaultStickyLinesProvider()); - } + private IEditorPart editorPart; /** * Creates a StickyScrollingHandler that will be linked to the given source viewer. The sticky @@ -87,8 +81,9 @@ public StickyScrollingHandler(ISourceViewer sourceViewer, IVerticalRuler vertica * @param stickyLinesProvider The sticky scrolling provider */ public StickyScrollingHandler(ISourceViewer sourceViewer, IVerticalRuler verticalRuler, IPreferenceStore preferenceStore, - IStickyLinesProvider stickyLinesProvider) { + IStickyLinesProvider stickyLinesProvider, IEditorPart editorPart) { this.sourceViewer= sourceViewer; + this.editorPart= editorPart; throttler= new Throttler(sourceViewer.getTextWidget().getDisplay(), Duration.ofMillis(THROTTLER_DELAY), this::calculateAndShowStickyLines); this.stickyLinesProvider= stickyLinesProvider; @@ -139,7 +134,7 @@ private StickyScrollingControlSettings loadControlSettings(IPreferenceStore stor private StickyLinesProperties loadStickyLinesProperties(IPreferenceStore store) { int tabWidth= store.getInt(EDITOR_TAB_WIDTH); - return new StickyLinesProperties(tabWidth); + return new StickyLinesProperties(tabWidth, editorPart); } @Override diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractDecoratedTextEditor.java b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractDecoratedTextEditor.java index e0b8c449331..ed44a1ad69b 100644 --- a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractDecoratedTextEditor.java +++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractDecoratedTextEditor.java @@ -148,6 +148,7 @@ import org.eclipse.ui.internal.texteditor.FocusedInformationPresenter; import org.eclipse.ui.internal.texteditor.LineNumberColumn; import org.eclipse.ui.internal.texteditor.TextChangeHover; +import org.eclipse.ui.internal.texteditor.stickyscroll.StickyLinesProviderRegistry; import org.eclipse.ui.internal.texteditor.stickyscroll.StickyScrollingHandler; import org.eclipse.ui.keys.IBindingService; import org.eclipse.ui.operations.NonLocalUndoUserApprover; @@ -162,6 +163,7 @@ import org.eclipse.ui.texteditor.rulers.RulerColumnDescriptor; import org.eclipse.ui.texteditor.rulers.RulerColumnPreferenceAdapter; import org.eclipse.ui.texteditor.rulers.RulerColumnRegistry; +import org.eclipse.ui.texteditor.stickyscroll.IStickyLinesProvider; import org.eclipse.ui.editors.text.DefaultEncodingSupport; import org.eclipse.ui.editors.text.EditorsUI; @@ -502,7 +504,8 @@ public void createPartControl(Composite parent) { createOverviewRulerContextMenu(); if (isStickyScrollingEnabled()) { - fStickyScrollingHandler= new StickyScrollingHandler(getSourceViewer(), getVerticalRuler(), getPreferenceStore()); + IStickyLinesProvider stickyLineProvider= getStickyLinesProvider(); + fStickyScrollingHandler= new StickyScrollingHandler(getSourceViewer(), getVerticalRuler(), getPreferenceStore(), stickyLineProvider, this); } } @@ -510,6 +513,11 @@ private boolean isStickyScrollingEnabled() { return getPreferenceStore().getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_STICKY_SCROLLING_ENABLED); } + private IStickyLinesProvider getStickyLinesProvider() { + StickyLinesProviderRegistry stickyLinesProviderRegistry= new StickyLinesProviderRegistry(); + return stickyLinesProviderRegistry.getProvider(getSourceViewer(), this); + } + /** * Creates the context menu for the overview ruler. *

@@ -931,7 +939,8 @@ protected void handlePreferenceStoreChanged(PropertyChangeEvent event) { return; if (store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_STICKY_SCROLLING_ENABLED)) { - fStickyScrollingHandler= new StickyScrollingHandler(getSourceViewer(), getVerticalRuler(), store); + IStickyLinesProvider stickyLineProvider= getStickyLinesProvider(); + fStickyScrollingHandler= new StickyScrollingHandler(getSourceViewer(), getVerticalRuler(), getPreferenceStore(), stickyLineProvider, this); //fire once fStickyScrollingHandler.viewportChanged(getSourceViewer().getTextWidget().getTopPixel()); } else { diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/IStickyLine.java b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/stickyscroll/IStickyLine.java similarity index 94% rename from bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/IStickyLine.java rename to bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/stickyscroll/IStickyLine.java index 33e54dc9cc6..c715c9286fe 100644 --- a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/IStickyLine.java +++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/stickyscroll/IStickyLine.java @@ -11,12 +11,14 @@ * Contributors: * SAP SE - initial API and implementation *******************************************************************************/ -package org.eclipse.ui.internal.texteditor.stickyscroll; +package org.eclipse.ui.texteditor.stickyscroll; import org.eclipse.swt.custom.StyleRange; /** * Representation of a sticky line. + * + * since 3.20 */ public interface IStickyLine { diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/IStickyLinesProvider.java b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/stickyscroll/IStickyLinesProvider.java similarity index 85% rename from bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/IStickyLinesProvider.java rename to bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/stickyscroll/IStickyLinesProvider.java index cb677202fca..44a0e116892 100644 --- a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/IStickyLinesProvider.java +++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/stickyscroll/IStickyLinesProvider.java @@ -11,17 +11,19 @@ * Contributors: * SAP SE - initial API and implementation *******************************************************************************/ -package org.eclipse.ui.internal.texteditor.stickyscroll; +package org.eclipse.ui.texteditor.stickyscroll; import java.util.List; import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.ui.IEditorPart; + /** * A sticky lines provider calculates the sticky lines for a given source viewer. The sticky lines * will be displayed in the top area of the editor. * - * TODO move to public package and add since 3.19 + * since 3.20 TODO: version bump in extra commit */ public interface IStickyLinesProvider { @@ -42,8 +44,9 @@ public interface IStickyLinesProvider { * Additional properties and access in order to calculate the sticky lines. * * @param tabWith The with of a tab + * @param editor The editor for which the sticky lines should be provided */ - record StickyLinesProperties(int tabWith) { + record StickyLinesProperties(int tabWith, IEditorPart editor) { } } diff --git a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLine.java b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/stickyscroll/StickyLine.java similarity index 71% rename from bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLine.java rename to bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/stickyscroll/StickyLine.java index 3533ad07c22..7488a28dcf5 100644 --- a/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLine.java +++ b/bundles/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/stickyscroll/StickyLine.java @@ -11,7 +11,7 @@ * Contributors: * SAP SE - initial API and implementation *******************************************************************************/ -package org.eclipse.ui.internal.texteditor.stickyscroll; +package org.eclipse.ui.texteditor.stickyscroll; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; @@ -20,8 +20,10 @@ import org.eclipse.jface.text.source.ISourceViewer; /** - * Default implementation of {@link IStickyLine}. Information about the text and style ranges are - * calculated from the given text widget. + * Default implementation of {@link IStickyLine}. Information about the text and + * style ranges are calculated from the given text widget. + * + * since 3.20 */ public class StickyLine implements IStickyLine { @@ -32,8 +34,8 @@ public class StickyLine implements IStickyLine { protected ISourceViewer sourceViewer; public StickyLine(int lineNumber, ISourceViewer sourceViewer) { - this.lineNumber= lineNumber; - this.sourceViewer= sourceViewer; + this.lineNumber = lineNumber; + this.sourceViewer = sourceViewer; } @Override @@ -44,19 +46,19 @@ public int getLineNumber() { @Override public String getText() { if (text == null) { - StyledText textWidget= sourceViewer.getTextWidget(); - text= textWidget.getLine(getWidgetLineNumber()); + StyledText textWidget = sourceViewer.getTextWidget(); + text = textWidget.getLine(getWidgetLineNumber()); } return text; } @Override public StyleRange[] getStyleRanges() { - StyledText textWidget= sourceViewer.getTextWidget(); - int offsetAtLine= textWidget.getOffsetAtLine(getWidgetLineNumber()); - StyleRange[] styleRanges= textWidget.getStyleRanges(offsetAtLine, getText().length()); + StyledText textWidget = sourceViewer.getTextWidget(); + int offsetAtLine = textWidget.getOffsetAtLine(getWidgetLineNumber()); + StyleRange[] styleRanges = textWidget.getStyleRanges(offsetAtLine, getText().length()); for (StyleRange styleRange : styleRanges) { - styleRange.start= styleRange.start - offsetAtLine; + styleRange.start = styleRange.start - offsetAtLine; } return styleRanges; } diff --git a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/editors/tests/EditorsTestSuite.java b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/editors/tests/EditorsTestSuite.java index 5bea44de374..65c6adde4a3 100644 --- a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/editors/tests/EditorsTestSuite.java +++ b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/editors/tests/EditorsTestSuite.java @@ -22,9 +22,12 @@ import org.eclipse.jface.text.tests.codemining.CodeMiningTest; import org.eclipse.ui.internal.texteditor.stickyscroll.DefaultStickyLinesProviderTest; +import org.eclipse.ui.internal.texteditor.stickyscroll.StickyLinesProviderRegistryTest; import org.eclipse.ui.internal.texteditor.stickyscroll.StickyScrollingControlTest; import org.eclipse.ui.internal.texteditor.stickyscroll.StickyScrollingHandlerTest; +import org.eclipse.ui.texteditor.stickyscroll.StickyLineTest; + /** * Test Suite for org.eclipse.ui.editors. * @@ -51,6 +54,8 @@ StickyScrollingControlTest.class, StickyScrollingHandlerTest.class, DefaultStickyLinesProviderTest.class, + StickyLineTest.class, + StickyLinesProviderRegistryTest.class, CodeMiningTest.class, }) diff --git a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/DefaultStickyLinesProviderTest.java b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/DefaultStickyLinesProviderTest.java index 8aaf61e0310..87102871347 100644 --- a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/DefaultStickyLinesProviderTest.java +++ b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/DefaultStickyLinesProviderTest.java @@ -17,6 +17,7 @@ import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; import java.util.List; @@ -35,7 +36,10 @@ import org.eclipse.jface.text.source.IVerticalRuler; import org.eclipse.jface.text.source.SourceViewer; -import org.eclipse.ui.internal.texteditor.stickyscroll.IStickyLinesProvider.StickyLinesProperties; +import org.eclipse.ui.IEditorPart; + +import org.eclipse.ui.texteditor.stickyscroll.IStickyLine; +import org.eclipse.ui.texteditor.stickyscroll.IStickyLinesProvider.StickyLinesProperties; public class DefaultStickyLinesProviderTest { @@ -44,6 +48,7 @@ public class DefaultStickyLinesProviderTest { private DefaultStickyLinesProvider stickyLinesProvider; private StyledText textWidget; private StickyLinesProperties stickyLinesProperties; + private IEditorPart editorPart; @Before public void setup() { @@ -52,7 +57,8 @@ public void setup() { sourceViewer.setDocument(new Document()); stickyLinesProvider = new DefaultStickyLinesProvider(); textWidget = sourceViewer.getTextWidget(); - stickyLinesProperties = new StickyLinesProperties(4); + editorPart = mock(IEditorPart.class); + stickyLinesProperties = new StickyLinesProperties(4, editorPart); } @Test @@ -125,7 +131,7 @@ public void testIgnoreEmptyLines() { @Test public void testLinesWithTabs() { - stickyLinesProperties = new StickyLinesProperties(2); + stickyLinesProperties = new StickyLinesProperties(2, editorPart); String text = """ line 1 \tline 2 diff --git a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLinesProviderRegistryTest.java b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLinesProviderRegistryTest.java new file mode 100644 index 00000000000..165647e49bb --- /dev/null +++ b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLinesProviderRegistryTest.java @@ -0,0 +1,63 @@ +package org.eclipse.ui.internal.texteditor.stickyscroll; + +import static org.eclipse.ui.editors.text.EditorsUI.PLUGIN_ID; +import static org.eclipse.ui.internal.texteditor.stickyscroll.StickyLinesProviderRegistry.STICKY_LINES_PROVIDERS_EXTENSION_POINT; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionRegistry; + +import org.eclipse.jface.text.source.ISourceViewer; + +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.stickyscroll.IStickyLinesProvider; + +public class StickyLinesProviderRegistryTest { + + private StickyLinesProviderDescriptor stickyLinesProviderDescriptor; + private StickyLinesProviderRegistry cut; + private ISourceViewer viewer; + private ITextEditor editor; + + @Before + public void setup() { + IConfigurationElement[] configurationElement = { mock(IConfigurationElement.class) }; + stickyLinesProviderDescriptor = mock(StickyLinesProviderDescriptor.class); + viewer = mock(ISourceViewer.class); + editor = mock(ITextEditor.class); + + IExtensionRegistry extensionRegistry = mock(IExtensionRegistry.class); + when(extensionRegistry.getConfigurationElementsFor(PLUGIN_ID, STICKY_LINES_PROVIDERS_EXTENSION_POINT)) + .thenReturn(configurationElement); + + cut = new StickyLinesProviderRegistry(extensionRegistry, e -> stickyLinesProviderDescriptor); + } + + @Test + public void testGetDefaultProviderIfNoMatch() { + when(stickyLinesProviderDescriptor.matches(viewer, editor)).thenReturn(false); + + IStickyLinesProvider provider = cut.getProvider(viewer, editor); + + assertThat(provider, instanceOf(DefaultStickyLinesProvider.class)); + } + + @Test + public void testGetProviderForMatch() { + IStickyLinesProvider expProvider = mock(IStickyLinesProvider.class); + when(stickyLinesProviderDescriptor.matches(viewer, editor)).thenReturn(true); + when(stickyLinesProviderDescriptor.createStickyLinesProvider()).thenReturn(expProvider); + + IStickyLinesProvider provider = cut.getProvider(viewer, editor); + + assertThat(provider, is(expProvider)); + } + +} diff --git a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControlTest.java b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControlTest.java index 4b8e63506de..c8d5faa1bad 100644 --- a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControlTest.java +++ b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingControlTest.java @@ -46,6 +46,8 @@ import org.eclipse.jface.text.source.IVerticalRuler; import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.ui.texteditor.stickyscroll.IStickyLine; + public class StickyScrollingControlTest { private Shell shell; diff --git a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingHandlerTest.java b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingHandlerTest.java index 0856c70b19e..24bd8d9ce04 100644 --- a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingHandlerTest.java +++ b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyScrollingHandlerTest.java @@ -53,7 +53,11 @@ import org.eclipse.jface.text.source.CompositeRuler; import org.eclipse.jface.text.source.SourceViewer; -import org.eclipse.ui.internal.texteditor.stickyscroll.IStickyLinesProvider.StickyLinesProperties; +import org.eclipse.ui.IEditorPart; + +import org.eclipse.ui.texteditor.stickyscroll.IStickyLine; +import org.eclipse.ui.texteditor.stickyscroll.IStickyLinesProvider; +import org.eclipse.ui.texteditor.stickyscroll.IStickyLinesProvider.StickyLinesProperties; public class StickyScrollingHandlerTest { @@ -67,6 +71,7 @@ public class StickyScrollingHandlerTest { private StickyScrollingHandler stickyScrollingHandler; private StickyLinesProperties stickyLinesProperties; private StyledText textWidget; + private IEditorPart editorPart; @Before public void setup() { @@ -79,6 +84,7 @@ public void setup() { textWidget = sourceViewer.getTextWidget(); textWidget.setText("first 1 \nline 2 \nline 3 \nline 4 \nline 5 \nline 6 \nline 7 \nline 8 \nline 9 \nline 10"); textWidget.setTopIndex(1); + editorPart = mock(IEditorPart.class); lineNumberColor = new Color(0, 0, 0); hoverColor = new Color(1, 1, 1); @@ -86,8 +92,8 @@ public void setup() { store = createPreferenceStore(); linesProvider = mock(IStickyLinesProvider.class); - stickyScrollingHandler = new StickyScrollingHandler(sourceViewer, ruler, store, linesProvider); - stickyLinesProperties = new StickyLinesProperties(4); + stickyScrollingHandler = new StickyScrollingHandler(sourceViewer, ruler, store, linesProvider, editorPart); + stickyLinesProperties = new StickyLinesProperties(4, editorPart); } @After diff --git a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLineTest.java b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/texteditor/stickyscroll/StickyLineTest.java similarity index 98% rename from tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLineTest.java rename to tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/texteditor/stickyscroll/StickyLineTest.java index 99ee26000f0..0f85d861ba8 100644 --- a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/internal/texteditor/stickyscroll/StickyLineTest.java +++ b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/ui/texteditor/stickyscroll/StickyLineTest.java @@ -11,7 +11,7 @@ * Contributors: * SAP SE - initial API and implementation *******************************************************************************/ -package org.eclipse.ui.internal.texteditor.stickyscroll; +package org.eclipse.ui.texteditor.stickyscroll; import static org.junit.Assert.assertEquals;