blob: 595f273800919b088457ffa676290880eae0e439 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2013, 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.assist;
import org.eclipse.jface.text.AbstractDocument;
import org.eclipse.jface.text.contentassist.ContentAssistEvent;
import org.eclipse.jface.text.contentassist.ICompletionListener;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
import org.eclipse.statet.ltk.model.core.element.SourceUnit;
import org.eclipse.statet.ltk.ui.sourceediting.SourceEditor;
public class ReshowCompletionsRunnable implements Runnable, Listener, ICompletionListener {
// Snapshot of current state
private final SourceEditor editor;
private final ISourceViewer viewer;
private final SourceUnit su;
private final AbstractDocument document;
private final long documentStamp;
private final Point selection;
private final Display display;
private final ContentAssist assist;
private boolean assistSelection;
public ReshowCompletionsRunnable(final SourceEditor editor, final ContentAssist assist) {
this.editor= editor;
this.viewer= editor.getViewer();
this.su= editor.getSourceUnit();
this.document= (AbstractDocument) this.viewer.getDocument();
this.documentStamp= this.document.getModificationStamp();
this.selection= this.viewer.getSelectedRange();
this.assist= assist;
this.display= this.viewer.getTextWidget().getDisplay();
this.display.addFilter(SWT.Verify, this);
this.display.addFilter(SWT.FocusOut, this);
this.assist.addCompletionListener(this);
}
protected void dispose() {
if (this.display.isDisposed()) {
return;
}
this.display.removeFilter(SWT.Verify, this);
this.display.removeFilter(SWT.FocusOut, this);
this.assist.removeCompletionListener(this);
}
private boolean isValid() {
return (UIAccess.isOkToUse(ReshowCompletionsRunnable.this.viewer.getTextWidget())
&& (this.viewer.getTextWidget().isFocusControl()
|| this.assist.hasProposalPopupFocus())
&& this.editor.getViewer() == this.viewer
&& this.editor.getSourceUnit() == this.su
&& this.viewer.getDocument() == this.document
&& this.document.getModificationStamp() == this.documentStamp
&& this.viewer.getSelectedRange().equals(this.selection) );
}
protected void cancel() {
dispose();
}
@Override
public void handleEvent(final Event event) {
switch (event.type) {
case SWT.FocusOut:
this.display.asyncExec(new Runnable() {
@Override
public void run() {
if (!isValid()) {
cancel();
}
}
});
break;
default:
cancel();
break;
}
}
@Override
public void assistSessionStarted(final ContentAssistEvent event) {
cancel();
}
@Override
public void assistSessionEnded(final ContentAssistEvent event) {
if (!this.assistSelection) {
return;
}
cancel();
}
@Override
public void selectionChanged(final ICompletionProposal proposal, final boolean smartToggle) {
if (!this.assistSelection) {
this.assistSelection= true;
return;
}
cancel();
}
protected boolean showCompletionsNow() {
return true;
}
@Override
public void run() {
if (this.display.isDisposed()) {
return;
}
this.display.asyncExec(new Runnable() {
@Override
public void run() {
dispose();
if (isValid() && showCompletionsNow()) {
ReshowCompletionsRunnable.this.assist.showPossibleCompletions(true, true);
}
}
});
}
}