Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/GenericEditorContentAssistant.java')
-rw-r--r--org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/GenericEditorContentAssistant.java145
1 files changed, 145 insertions, 0 deletions
diff --git a/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/GenericEditorContentAssistant.java b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/GenericEditorContentAssistant.java
new file mode 100644
index 00000000000..62953a95310
--- /dev/null
+++ b/org.eclipse.ui.genericeditor/src/org/eclipse/ui/internal/genericeditor/GenericEditorContentAssistant.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2021 Christoph Läubrich and others.
+ *
+ * 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:
+ * Christoph Läubrich - Inital API and implementation
+ *******************************************************************************/
+package org.eclipse.ui.internal.genericeditor;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.text.AbstractReusableInformationControlCreator;
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Extension of the ContentAssistant that supports the following additional
+ * features:
+ * <ul>
+ * <li>#updateTokens refresh the registration of
+ * {@link IContentAssistProcessor}s on document changes</li>
+ * <li>Using a ContentTypeRelatedExtensionTracker to dynamically track
+ * IContentAssistProcessor in the OSGi service registry
+ * </ul>
+ *
+ * @author christoph
+ *
+ */
+public class GenericEditorContentAssistant extends ContentAssistant {
+ private static final DefaultContentAssistProcessor DEFAULT_CONTENT_ASSIST_PROCESSOR = new DefaultContentAssistProcessor();
+ private ContentTypeRelatedExtensionTracker<IContentAssistProcessor> contentAssistProcessorTracker;
+ private Set<IContentType> types;
+ private List<IContentAssistProcessor> processors;
+
+ /**
+ * Creates a new GenericEditorContentAssistant instance for the given content
+ * types and contentAssistProcessorTracker
+ *
+ * @param contentAssistProcessorTracker the tracker to use for tracking
+ * additional
+ * {@link IContentAssistProcessor}s in the
+ * OSGi service factory
+ * @param processors the static processor list
+ * @param types the {@link IContentType} that are used
+ * to filter appropriate candidates from
+ * the registry
+ */
+ public GenericEditorContentAssistant(
+ ContentTypeRelatedExtensionTracker<IContentAssistProcessor> contentAssistProcessorTracker,
+ List<IContentAssistProcessor> processors, Set<IContentType> types) {
+ super(true);
+ this.contentAssistProcessorTracker = contentAssistProcessorTracker;
+ this.processors = Objects.requireNonNullElseGet(processors, () -> Collections.emptyList());
+ this.types = types;
+
+ setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_BELOW);
+ setProposalPopupOrientation(IContentAssistant.PROPOSAL_REMOVE);
+ setAutoActivationDelay(0);
+ enableColoredLabels(true);
+ enableAutoActivation(true);
+ setInformationControlCreator(new AbstractReusableInformationControlCreator() {
+ @Override
+ protected IInformationControl doCreateInformationControl(Shell parent) {
+ return new DefaultInformationControl(parent);
+ }
+ });
+ }
+
+ /**
+ * Updates the {@link IContentAssistProcessor} registrations according to the
+ * documents content-type tokens
+ *
+ * @param document the document to use for updating the tokens
+ */
+ public void updateTokens(IDocument document) {
+ updateProcessors(document);
+ contentAssistProcessorTracker.getTracked().stream().filter(s -> s.isPresent()).map(s -> s.get())
+ .forEach(p -> updateProcessorToken(p, document));
+ }
+
+ private void updateProcessors(IDocument iDocument) {
+ if (processors.isEmpty()) {
+ updateProcessorToken(DEFAULT_CONTENT_ASSIST_PROCESSOR, iDocument);
+ } else {
+ for (IContentAssistProcessor processor : processors) {
+ updateProcessorToken(processor, iDocument);
+ }
+ }
+ }
+
+ private void updateProcessorToken(IContentAssistProcessor processor, IDocument document) {
+ removeContentAssistProcessor(processor);
+ addContentAssistProcessor(processor, IDocument.DEFAULT_CONTENT_TYPE);
+ if (document != null) {
+ for (String contentType : document.getLegalContentTypes()) {
+ addContentAssistProcessor(processor, contentType);
+ }
+ }
+ if (processor != DEFAULT_CONTENT_ASSIST_PROCESSOR) {
+ removeContentAssistProcessor(DEFAULT_CONTENT_ASSIST_PROCESSOR);
+ }
+ }
+
+ @Override
+ public void uninstall() {
+ contentAssistProcessorTracker.stopTracking();
+ super.uninstall();
+ }
+
+ @Override
+ public void install(ITextViewer textViewer) {
+ super.install(textViewer);
+ updateProcessors(textViewer.getDocument());
+ contentAssistProcessorTracker.onAdd(added -> {
+ if (types.contains(added.getContentType())) {
+ IContentAssistProcessor processor = added.get();
+ if (processor != null) {
+ updateProcessorToken(processor, textViewer.getDocument());
+ }
+ }
+ });
+ contentAssistProcessorTracker.onRemove(removed -> {
+ if (removed.isPresent()) {
+ removeContentAssistProcessor(removed.get());
+ }
+ });
+ contentAssistProcessorTracker.startTracking();
+ }
+}

Back to the top