blob: af6d754196e3cd9a76b104606053d9868e19c1cf [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
* Mickael Istria (Red Hat Inc.) - [251156] Allow multiple contentAssitProviders internally & inheritance
* Stephan Wahlbrink <sw@wahlbrink.eu> - Bug 512251 - Fix IllegalArgumentException in ContextInformationPopup
*******************************************************************************/
package org.eclipse.jface.text.contentassist;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Control;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.contentassist.IContentAssistSubjectControl;
import org.eclipse.jface.contentassist.ISubjectControlContextInformationPresenter;
import org.eclipse.jface.contentassist.ISubjectControlContextInformationValidator;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IEventConsumer;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITextViewerExtension;
import org.eclipse.jface.text.contentassist.ContextInformationPopup.ContextFrame;
/**
* This content assist adapter delegates the calls either to
* a text viewer or to a content assist subject control.
*
* @since 3.0
*/
class ContentAssistSubjectControlAdapter implements IContentAssistSubjectControl {
/**
* The text viewer which is used as content assist subject control.
*/
protected ITextViewer fViewer;
/**
* The content assist subject control.
*/
protected IContentAssistSubjectControl fContentAssistSubjectControl;
/**
* Creates an adapter for the given content assist subject control.
*
* @param contentAssistSubjectControl the content assist subject control
*/
ContentAssistSubjectControlAdapter(IContentAssistSubjectControl contentAssistSubjectControl) {
Assert.isNotNull(contentAssistSubjectControl);
fContentAssistSubjectControl= contentAssistSubjectControl;
}
/**
* Creates an adapter for the given text viewer.
*
* @param viewer the text viewer
*/
public ContentAssistSubjectControlAdapter(ITextViewer viewer) {
Assert.isNotNull(viewer);
fViewer= viewer;
}
@Override
public int getLineHeight() {
if (fContentAssistSubjectControl != null)
return fContentAssistSubjectControl.getLineHeight();
return fViewer.getTextWidget().getLineHeight(getCaretOffset());
}
@Override
public Control getControl() {
if (fContentAssistSubjectControl != null)
return fContentAssistSubjectControl.getControl();
return fViewer.getTextWidget();
}
@Override
public Point getLocationAtOffset(int offset) {
if (fContentAssistSubjectControl != null)
return fContentAssistSubjectControl.getLocationAtOffset(offset);
return fViewer.getTextWidget().getLocationAtOffset(offset);
}
@Override
public Point getWidgetSelectionRange() {
if (fContentAssistSubjectControl != null)
return fContentAssistSubjectControl.getWidgetSelectionRange();
return fViewer.getTextWidget().getSelectionRange();
}
@Override
public Point getSelectedRange() {
if (fContentAssistSubjectControl != null)
return fContentAssistSubjectControl.getSelectedRange();
return fViewer.getSelectedRange();
}
@Override
public int getCaretOffset() {
if (fContentAssistSubjectControl != null)
return fContentAssistSubjectControl.getCaretOffset();
return fViewer.getTextWidget().getCaretOffset();
}
@Override
public String getLineDelimiter() {
if (fContentAssistSubjectControl != null)
return fContentAssistSubjectControl.getLineDelimiter();
return fViewer.getTextWidget().getLineDelimiter();
}
public boolean isValidWidgetOffset(int widgetOffset) {
if (fContentAssistSubjectControl != null) {
IDocument document= fContentAssistSubjectControl.getDocument();
return (widgetOffset >= 0 && widgetOffset <= document.getLength());
}
return (widgetOffset >= 0 && widgetOffset <= fViewer.getTextWidget().getCharCount());
}
@Override
public void addKeyListener(KeyListener keyListener) {
if (fContentAssistSubjectControl != null)
fContentAssistSubjectControl.addKeyListener(keyListener);
else
fViewer.getTextWidget().addKeyListener(keyListener);
}
@Override
public void removeKeyListener(KeyListener keyListener) {
if (fContentAssistSubjectControl != null)
fContentAssistSubjectControl.removeKeyListener(keyListener);
else
fViewer.getTextWidget().removeKeyListener(keyListener);
}
@Override
public IDocument getDocument() {
if (fContentAssistSubjectControl != null)
return fContentAssistSubjectControl.getDocument();
return fViewer.getDocument();
}
@Override
public boolean prependVerifyKeyListener(VerifyKeyListener verifyKeyListener) {
if (fContentAssistSubjectControl != null) {
return fContentAssistSubjectControl.prependVerifyKeyListener(verifyKeyListener);
} else if (fViewer instanceof ITextViewerExtension) {
ITextViewerExtension e= (ITextViewerExtension) fViewer;
e.prependVerifyKeyListener(verifyKeyListener);
return true;
} else {
StyledText textWidget= fViewer.getTextWidget();
if (Helper.okToUse(textWidget)) {
textWidget.addVerifyKeyListener(verifyKeyListener);
return true;
}
}
return false;
}
@Override
public boolean appendVerifyKeyListener(VerifyKeyListener verifyKeyListener) {
if (fContentAssistSubjectControl != null)
return fContentAssistSubjectControl.appendVerifyKeyListener(verifyKeyListener);
else if (fViewer instanceof ITextViewerExtension) {
ITextViewerExtension extension= (ITextViewerExtension)fViewer;
extension.appendVerifyKeyListener(verifyKeyListener);
return true;
} else {
StyledText textWidget= fViewer.getTextWidget();
if (Helper.okToUse(textWidget)) {
textWidget.addVerifyKeyListener(verifyKeyListener);
return true;
}
}
return false;
}
@Override
public void removeVerifyKeyListener(VerifyKeyListener verifyKeyListener) {
if (fContentAssistSubjectControl != null) {
fContentAssistSubjectControl.removeVerifyKeyListener(verifyKeyListener);
} else if (fViewer instanceof ITextViewerExtension) {
ITextViewerExtension extension= (ITextViewerExtension) fViewer;
extension.removeVerifyKeyListener(verifyKeyListener);
} else {
StyledText textWidget= fViewer.getTextWidget();
if (Helper.okToUse(textWidget))
textWidget.removeVerifyKeyListener(verifyKeyListener);
}
}
@Override
public void setEventConsumer(IEventConsumer eventConsumer) {
if (fContentAssistSubjectControl != null)
fContentAssistSubjectControl.setEventConsumer(eventConsumer);
else
fViewer.setEventConsumer(eventConsumer);
}
@Override
public void setSelectedRange(int i, int j) {
if (fContentAssistSubjectControl != null)
fContentAssistSubjectControl.setSelectedRange(i, j);
else
fViewer.setSelectedRange(i, j);
}
@Override
public void revealRange(int i, int j) {
if (fContentAssistSubjectControl != null)
fContentAssistSubjectControl.revealRange(i, j);
else
fViewer.revealRange(i, j);
}
/*
* @see org.eclipse.jface.text.contentassist.IContentAssistSubjectControl#canAddVerifyKeyListener()
*/
@Override
public boolean supportsVerifyKeyListener() {
if (fContentAssistSubjectControl != null)
return fContentAssistSubjectControl.supportsVerifyKeyListener();
return true;
}
/**
* Returns the characters which when typed by the user should automatically
* initiate proposing completions. The position is used to determine the
* appropriate content assist processor to invoke.
*
* @param contentAssistant the content assistant
* @param offset a document offset
* @return the auto activation characters
* @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
*/
public char[] getCompletionProposalAutoActivationCharacters(ContentAssistant contentAssistant, int offset) {
if (fContentAssistSubjectControl != null)
return contentAssistant.getCompletionProposalAutoActivationCharacters(fContentAssistSubjectControl, offset);
return contentAssistant.getCompletionProposalAutoActivationCharacters(fViewer, offset);
}
/**
* Returns the characters which when typed by the user should automatically
* initiate the presentation of context information. The position is used
* to determine the appropriate content assist processor to invoke.
*
* @param contentAssistant the content assistant
* @param offset a document offset
* @return the auto activation characters
*
* @see IContentAssistProcessor#getContextInformationAutoActivationCharacters()
*/
char[] getContextInformationAutoActivationCharacters(ContentAssistant contentAssistant, int offset) {
if (fContentAssistSubjectControl != null)
return contentAssistant.getContextInformationAutoActivationCharacters(fContentAssistSubjectControl, offset);
return contentAssistant.getContextInformationAutoActivationCharacters(fViewer, offset);
}
/**
* Creates and returns a completion proposal popup for the given content assistant.
*
* @param contentAssistant the content assistant
* @param controller the additional info controller, or <code>null</code>
* @param asynchronous <true> if this content assistant should present the proposals
* asynchronously, <code>false</code> otherwise
* @return the completion proposal popup
*/
CompletionProposalPopup createCompletionProposalPopup(ContentAssistant contentAssistant, AdditionalInfoController controller, boolean asynchronous) {
if (asynchronous) {
if (fContentAssistSubjectControl != null)
return new AsyncCompletionProposalPopup(contentAssistant, fContentAssistSubjectControl, controller);
return new AsyncCompletionProposalPopup(contentAssistant, fViewer, controller);
} else {
if (fContentAssistSubjectControl != null)
return new CompletionProposalPopup(contentAssistant, fContentAssistSubjectControl, controller);
return new CompletionProposalPopup(contentAssistant, fViewer, controller);
}
}
/**
* Creates and returns a context info popup for the given content assistant.
*
* @param contentAssistant the content assistant
* @return the context info popup or <code>null</code>
*/
ContextInformationPopup createContextInfoPopup(ContentAssistant contentAssistant) {
if (fContentAssistSubjectControl != null)
return new ContextInformationPopup(contentAssistant, fContentAssistSubjectControl);
return new ContextInformationPopup(contentAssistant, fViewer);
}
/**
* Returns the context information validator that should be used to
* determine when the currently displayed context information should
* be dismissed. The position is used to determine the appropriate
* content assist processor to invoke.
*
* @param contentAssistant the content assistant
* @param offset a document offset
* @return an validator
*/
public IContextInformationValidator getContextInformationValidator(ContentAssistant contentAssistant, int offset) {
if (fContentAssistSubjectControl != null)
return contentAssistant.getContextInformationValidator(fContentAssistSubjectControl, offset);
return contentAssistant.getContextInformationValidator(fViewer, offset);
}
/**
* Returns the context information presenter that should be used to
* display context information. The position is used to determine the
* appropriate content assist processor to invoke.
*
* @param contentAssistant the content assistant
* @param offset a document offset
* @return a presenter
*/
public IContextInformationPresenter getContextInformationPresenter(ContentAssistant contentAssistant, int offset) {
if (fContentAssistSubjectControl != null)
return contentAssistant.getContextInformationPresenter(fContentAssistSubjectControl, offset);
return contentAssistant.getContextInformationPresenter(fViewer, offset);
}
/**
* Installs this adapter's information validator on the given context frame.
*
* @param frame the context frame
*/
public void installValidator(ContextFrame frame) {
if (fContentAssistSubjectControl != null) {
if (frame.fValidator instanceof ISubjectControlContextInformationValidator)
((ISubjectControlContextInformationValidator)frame.fValidator).install(frame.fInformation, fContentAssistSubjectControl, frame.fOffset);
} else
frame.fValidator.install(frame.fInformation, fViewer, frame.fOffset);
}
/**
* Installs this adapter's information presenter on the given context frame.
*
* @param frame the context frame
*/
public void installContextInformationPresenter(ContextFrame frame) {
if (fContentAssistSubjectControl != null) {
if (frame.fPresenter instanceof ISubjectControlContextInformationPresenter)
((ISubjectControlContextInformationPresenter)frame.fValidator).install(frame.fInformation, fContentAssistSubjectControl, frame.fBeginOffset);
} else
frame.fPresenter.install(frame.fInformation, fViewer, frame.fBeginOffset);
}
/**
* Returns an array of context information objects computed based
* on the specified document position. The position is used to determine
* the appropriate content assist processor to invoke.
*
* @param contentAssistant the content assistant
* @param offset a document offset
* @return an array of context information objects
* @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
*/
public IContextInformation[] computeContextInformation(ContentAssistant contentAssistant, int offset) {
if (fContentAssistSubjectControl != null)
return contentAssistant.computeContextInformation(fContentAssistSubjectControl, offset);
return contentAssistant.computeContextInformation(fViewer, offset);
}
@Override
public boolean addSelectionListener(SelectionListener selectionListener) {
if (fContentAssistSubjectControl != null)
return fContentAssistSubjectControl.addSelectionListener(selectionListener);
fViewer.getTextWidget().addSelectionListener(selectionListener);
return true;
}
@Override
public void removeSelectionListener(SelectionListener selectionListener) {
if (fContentAssistSubjectControl != null)
fContentAssistSubjectControl.removeSelectionListener(selectionListener);
else
fViewer.getTextWidget().removeSelectionListener(selectionListener);
}
}