前者按 http://blog.csdn.net/tomsheng321/article/details/39548627 修改
后者按 http://blog.csdn.net/lethwei/article/details/5837282 修改,同时注释了 accept 方法实现 和 去掉 Home End 键在提示窗口的上下定位
/*******************************************************************************
* Copyright (c) 2000, 2010 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
* Sean Montgomery, sean_montgomery@comcast.net - https://bugs.eclipse.org/bugs/show_bug.cgi?id=116454
*******************************************************************************/
package org.eclipse.jface.text.contentassist; import java.util.ArrayList;
import java.util.List; import org.eclipse.osgi.util.TextProcessor; import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem; import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.bindings.keys.KeySequence;
import org.eclipse.jface.bindings.keys.SWTKeySupport;
import org.eclipse.jface.contentassist.IContentAssistSubjectControl;
import org.eclipse.jface.internal.text.InformationControlReplacer;
import org.eclipse.jface.internal.text.TableOwnerDrawSupport;
import org.eclipse.jface.preference.JFacePreferences;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.Geometry;
import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.AbstractInformationControlManager.Anchor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IEditingSupport;
import org.eclipse.jface.text.IEditingSupportRegistry;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.IRewriteTarget;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITextViewerExtension;
import org.eclipse.jface.text.TextUtilities; /**
* This class is used to present proposals to the user. If additional
* information exists for a proposal, then selecting that proposal will result
* in the information being displayed in a secondary window.
*
* @see org.eclipse.jface.text.contentassist.ICompletionProposal
* @see org.eclipse.jface.text.contentassist.AdditionalInfoController
*/
class CompletionProposalPopup implements IContentAssistListener {
/**
* Set to <code>true</code> to use a Table with SWT.VIRTUAL. XXX: This is a
* workaround for: https://bugs.eclipse.org/bugs/show_bug.cgi?id=90321 More
* details see also: https://bugs.eclipse.org/bugs/show_bug.cgi?id=98585#c36
*
* @since 3.1
*/
private static final boolean USE_VIRTUAL = !"motif".equals(SWT.getPlatform()); //$NON-NLS-1$ /**
* Completion proposal selection handler.
*
* @since 3.4
*/
final class ProposalSelectionHandler extends AbstractHandler { /**
* Selection operation codes.
*/
static final int SELECT_NEXT = 1;
static final int SELECT_PREVIOUS = 2; private final int fOperationCode; /**
* Creates a new selection handler.
*
* @param operationCode
* the operation code
* @since 3.4
*/
public ProposalSelectionHandler(int operationCode) {
Assert.isLegal(operationCode == SELECT_NEXT || operationCode == SELECT_PREVIOUS);
fOperationCode = operationCode;
} /*
* @see
* org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core
* .commands.ExecutionEvent)
*
* @since 3.4
*/
public Object execute(ExecutionEvent event) throws ExecutionException {
int itemCount = fProposalTable.getItemCount();
int selectionIndex = fProposalTable.getSelectionIndex();
switch (fOperationCode) {
case SELECT_NEXT:
selectionIndex += 1;
if (selectionIndex > itemCount - 1)
selectionIndex = 0;
break;
case SELECT_PREVIOUS:
selectionIndex -= 1;
if (selectionIndex < 0)
selectionIndex = itemCount - 1;
break;
}
selectProposal(selectionIndex, false);
return null;
} } /**
* The empty proposal displayed if there is nothing else to show.
*
* @since 3.2
*/
private static final class EmptyProposal implements ICompletionProposal, ICompletionProposalExtension { String fDisplayString;
int fOffset; /*
* @see ICompletionProposal#apply(IDocument)
*/
public void apply(IDocument document) {
} /*
* @see ICompletionProposal#getSelection(IDocument)
*/
public Point getSelection(IDocument document) {
return new Point(fOffset, 0);
} /*
* @see ICompletionProposal#getContextInformation()
*/
public IContextInformation getContextInformation() {
return null;
} /*
* @see ICompletionProposal#getImage()
*/
public Image getImage() {
return null;
} /*
* @see ICompletionProposal#getDisplayString()
*/
public String getDisplayString() {
return fDisplayString;
} /*
* @see ICompletionProposal#getAdditionalProposalInfo()
*/
public String getAdditionalProposalInfo() {
return null;
} /*
* @see
* org.eclipse.jface.text.contentassist.ICompletionProposalExtension
* #apply(org.eclipse.jface.text.IDocument, char, int)
*/
public void apply(IDocument document, char trigger, int offset) {
} /*
* @see
* org.eclipse.jface.text.contentassist.ICompletionProposalExtension
* #isValidFor(org.eclipse.jface.text.IDocument, int)
*/
public boolean isValidFor(IDocument document, int offset) {
return false;
} /*
* @see
* org.eclipse.jface.text.contentassist.ICompletionProposalExtension
* #getTriggerCharacters()
*/
public char[] getTriggerCharacters() {
return null;
} /*
* @see
* org.eclipse.jface.text.contentassist.ICompletionProposalExtension
* #getContextInformationPosition()
*/
public int getContextInformationPosition() {
return -1;
}
} private final class ProposalSelectionListener implements KeyListener {
public void keyPressed(KeyEvent e) {
if (!Helper.okToUse(fProposalShell))
return; if (e.character == 0 && e.keyCode == SWT.CTRL) {
// http://dev.eclipse.org/bugs/show_bug.cgi?id=34754
int index = fProposalTable.getSelectionIndex();
if (index >= 0)
selectProposal(index, true);
}
} public void keyReleased(KeyEvent e) {
if (!Helper.okToUse(fProposalShell))
return; if (e.character == 0 && e.keyCode == SWT.CTRL) {
// http://dev.eclipse.org/bugs/show_bug.cgi?id=34754
int index = fProposalTable.getSelectionIndex();
if (index >= 0)
selectProposal(index, false);
}
}
} private final class CommandKeyListener extends KeyAdapter {
private final KeySequence fCommandSequence; private CommandKeyListener(KeySequence keySequence) {
fCommandSequence = keySequence;
} public void keyPressed(KeyEvent e) {
if (!Helper.okToUse(fProposalShell))
return; int accelerator = SWTKeySupport.convertEventToUnmodifiedAccelerator(e);
KeySequence sequence = KeySequence.getInstance(SWTKeySupport.convertAcceleratorToKeyStroke(accelerator));
if (sequence.equals(fCommandSequence))
if (fContentAssistant.isPrefixCompletionEnabled())
incrementalComplete();
else
showProposals(false); }
} /** The associated text viewer. */
private ITextViewer fViewer;
/** The associated content assistant. */
private final ContentAssistant fContentAssistant;
/** The used additional info controller, or <code>null</code> if none. */
private final AdditionalInfoController fAdditionalInfoController;
/** The closing strategy for this completion proposal popup. */
private final PopupCloser fPopupCloser = new PopupCloser();
/** The popup shell. */
private Shell fProposalShell;
/** The proposal table. */
private Table fProposalTable;
/** Indicates whether a completion proposal is being inserted. */
private boolean fInserting = false;
/** The key listener to control navigation. */
private ProposalSelectionListener fKeyListener;
/** List of document events used for filtering proposals. */
private final List fDocumentEvents = new ArrayList();
/** Listener filling the document event queue. */
private IDocumentListener fDocumentListener;
/** The filter list of proposals. */
private ICompletionProposal[] fFilteredProposals;
/** The computed list of proposals. */
private ICompletionProposal[] fComputedProposals;
/** The offset for which the proposals have been computed. */
private int fInvocationOffset;
/** The offset for which the computed proposals have been filtered. */
private int fFilterOffset;
/**
* The most recently selected proposal.
*
* @since 3.0
*/
private ICompletionProposal fLastProposal;
/**
* The content assist subject control. This replaces <code>fViewer</code>
*
* @since 3.0
*/
private IContentAssistSubjectControl fContentAssistSubjectControl;
/**
* The content assist subject control adapter. This replaces
* <code>fViewer</code>
*
* @since 3.0
*/
private final ContentAssistSubjectControlAdapter fContentAssistSubjectControlAdapter;
/**
* Remembers the size for this completion proposal popup.
*
* @since 3.0
*/
private Point fSize;
/**
* Editor helper that communicates that the completion proposal popup may
* have focus while the 'logical focus' is still with the editor.
*
* @since 3.1
*/
private IEditingSupport fFocusHelper;
/**
* Set to true by {@link #computeFilteredProposals(int, DocumentEvent)} if
* the returned proposals are a subset of {@link #fFilteredProposals},
* <code>false</code> if not.
*
* @since 3.1
*/
private boolean fIsFilteredSubset;
/**
* The filter runnable.
*
* @since 3.1.1
*/
private final Runnable fFilterRunnable = new Runnable() {
public void run() {
if (!fIsFilterPending)
return; fIsFilterPending = false; if (!Helper.okToUse(fContentAssistSubjectControlAdapter.getControl()))
return; int offset = fContentAssistSubjectControlAdapter.getSelectedRange().x;
ICompletionProposal[] proposals = null;
try {
if (offset > -1) {
DocumentEvent event = TextUtilities.mergeProcessedDocumentEvents(fDocumentEvents);
proposals = computeFilteredProposals(offset, event);
}
} catch (BadLocationException x) {
} finally {
fDocumentEvents.clear();
}
fFilterOffset = offset; if (proposals != null && proposals.length > 0)
setProposals(proposals, fIsFilteredSubset);
else
hide();
}
};
/**
* <code>true</code> if <code>fFilterRunnable</code> has been posted,
* <code>false</code> if not.
*
* @since 3.1.1
*/
private boolean fIsFilterPending = false;
/**
* The info message at the bottom of the popup, or <code>null</code> for no
* popup (if ContentAssistant does not provide one).
*
* @since 3.2
*/
private Label fMessageText;
/**
* The font used for <code>fMessageText</code> or null; dispose when done.
*
* @since 3.2
*/
private Font fMessageTextFont;
/**
* The most recent completion offset (used to determine repeated invocation)
*
* @since 3.2
*/
private int fLastCompletionOffset;
/**
* The (reusable) empty proposal.
*
* @since 3.2
*/
private final EmptyProposal fEmptyProposal = new EmptyProposal();
/**
* The text for the empty proposal, or <code>null</code> to use the default
* text.
*
* @since 3.2
*/
private String fEmptyMessage = null;
/**
* Tells whether colored labels support is enabled. Only valid while the
* popup is active.
*
* @since 3.4
*/
private boolean fIsColoredLabelsSupportEnabled = false; /**
* Creates a new completion proposal popup for the given elements.
*
* @param contentAssistant
* the content assistant feeding this popup
* @param viewer
* the viewer on top of which this popup appears
* @param infoController
* the information control collaborating with this popup, or
* <code>null</code>
* @since 2.0
*/
public CompletionProposalPopup(ContentAssistant contentAssistant, ITextViewer viewer, AdditionalInfoController infoController) {
fContentAssistant = contentAssistant;
fViewer = viewer;
fAdditionalInfoController = infoController;
fContentAssistSubjectControlAdapter = new ContentAssistSubjectControlAdapter(fViewer);
} /**
* Creates a new completion proposal popup for the given elements.
*
* @param contentAssistant
* the content assistant feeding this popup
* @param contentAssistSubjectControl
* the content assist subject control on top of which this popup
* appears
* @param infoController
* the information control collaborating with this popup, or
* <code>null</code>
* @since 3.0
*/
public CompletionProposalPopup(ContentAssistant contentAssistant, IContentAssistSubjectControl contentAssistSubjectControl, AdditionalInfoController infoController) {
fContentAssistant = contentAssistant;
fContentAssistSubjectControl = contentAssistSubjectControl;
fAdditionalInfoController = infoController;
fContentAssistSubjectControlAdapter = new ContentAssistSubjectControlAdapter(fContentAssistSubjectControl);
} /**
* Computes and presents completion proposals. The flag indicates whether
* this call has be made out of an auto activation context.
*
* @param autoActivated
* <code>true</code> if auto activation context
* @return an error message or <code>null</code> in case of no error
*/
public String showProposals(final boolean autoActivated) { if (fKeyListener == null)
fKeyListener = new ProposalSelectionListener(); final Control control = fContentAssistSubjectControlAdapter.getControl(); if (!Helper.okToUse(fProposalShell) && control != null && !control.isDisposed()) {
// add the listener before computing the proposals so we don't move
// the caret
// when the user types fast.
fContentAssistSubjectControlAdapter.addKeyListener(fKeyListener); BusyIndicator.showWhile(control.getDisplay(), new Runnable() {
public void run() { fInvocationOffset = fContentAssistSubjectControlAdapter.getSelectedRange().x;
fFilterOffset = fInvocationOffset;
fLastCompletionOffset = fFilterOffset;
fComputedProposals = computeProposals(fInvocationOffset); int count = (fComputedProposals == null ? 0 : fComputedProposals.length);
if (count == 0 && hideWhenNoProposals(autoActivated))
return; if (count == 1 && !autoActivated && canAutoInsert(fComputedProposals[0])) {
insertProposal(fComputedProposals[0], (char) 0, 0, fInvocationOffset);
hide();
} else {
createProposalSelector();
setProposals(fComputedProposals, false);
displayProposals();
}
}
});
} else {
fLastCompletionOffset = fFilterOffset;
handleRepeatedInvocation();
} return getErrorMessage();
} /**
* Hides the popup and returns <code>true</code> if the popup is configured
* to never display an empty list. Returns <code>false</code> otherwise.
*
* @param autoActivated
* whether the invocation was auto-activated
* @return <code>false</code> if an empty list should be displayed,
* <code>true</code> otherwise
* @since 3.2
*/
private boolean hideWhenNoProposals(boolean autoActivated) {
if (autoActivated || !fContentAssistant.isShowEmptyList()) {
if (!autoActivated) {
Control control = fContentAssistSubjectControlAdapter.getControl();
if (control != null && !control.isDisposed())
control.getDisplay().beep();
}
hide();
return true;
}
return false;
} /**
* If content assist is set up to handle cycling, then the proposals are
* recomputed. Otherwise, nothing happens.
*
* @since 3.2
*/
private void handleRepeatedInvocation() {
if (fContentAssistant.isRepeatedInvocationMode()) {
fComputedProposals = computeProposals(fFilterOffset);
setProposals(fComputedProposals, false);
}
} /**
* Returns the completion proposal available at the given offset of the
* viewer's document. Delegates the work to the content assistant.
*
* @param offset
* the offset
* @return the completion proposals available at this offset
*/
private ICompletionProposal[] computeProposals(int offset) {
if (fContentAssistSubjectControl != null)
return fContentAssistant.computeCompletionProposals(fContentAssistSubjectControl, offset);
return fContentAssistant.computeCompletionProposals(fViewer, offset);
} /**
* Returns the error message.
*
* @return the error message
*/
private String getErrorMessage() {
return fContentAssistant.getErrorMessage();
} /**
* Creates the proposal selector.
*/
private void createProposalSelector() {
if (Helper.okToUse(fProposalShell))
return; Control control = fContentAssistSubjectControlAdapter.getControl();
fProposalShell = new Shell(control.getShell(), SWT.ON_TOP | SWT.RESIZE);
fProposalShell.setFont(JFaceResources.getDefaultFont());
if (USE_VIRTUAL) {
fProposalTable = new Table(fProposalShell, SWT.H_SCROLL | SWT.V_SCROLL | SWT.VIRTUAL); Listener listener = new Listener() {
public void handleEvent(Event event) {
handleSetData(event);
}
};
fProposalTable.addListener(SWT.SetData, listener);
} else {
fProposalTable = new Table(fProposalShell, SWT.H_SCROLL | SWT.V_SCROLL);
} fIsColoredLabelsSupportEnabled = fContentAssistant.isColoredLabelsSupportEnabled();
if (fIsColoredLabelsSupportEnabled)
TableOwnerDrawSupport.install(fProposalTable); fProposalTable.setLocation(0, 0);
if (fAdditionalInfoController != null)
fAdditionalInfoController.setSizeConstraints(50, 10, true, true); GridLayout layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0;
layout.verticalSpacing = 1;
fProposalShell.setLayout(layout); if (fContentAssistant.isStatusLineVisible()) {
createMessageText();
} GridData data = new GridData(GridData.FILL_BOTH); Point size = fContentAssistant.restoreCompletionProposalPopupSize();
if (size != null) {
fProposalTable.setLayoutData(data);
fProposalShell.setSize(size);
} else {
int height = fProposalTable.getItemHeight() * 10;
// use golden ratio as default aspect ratio
final double aspectRatio = (1 + Math.sqrt(5)) / 2;
int width = (int) (height * aspectRatio);
Rectangle trim = fProposalTable.computeTrim(0, 0, width, height);
data.heightHint = trim.height;
data.widthHint = trim.width;
fProposalTable.setLayoutData(data);
fProposalShell.pack();
}
fContentAssistant.addToLayout(this, fProposalShell, ContentAssistant.LayoutManager.LAYOUT_PROPOSAL_SELECTOR, fContentAssistant.getSelectionOffset()); fProposalShell.addControlListener(new ControlListener() { public void controlMoved(ControlEvent e) {
} public void controlResized(ControlEvent e) {
if (fAdditionalInfoController != null) {
// reset the cached resize constraints
fAdditionalInfoController.setSizeConstraints(50, 10, true, false);
fAdditionalInfoController.hideInformationControl();
fAdditionalInfoController.handleTableSelectionChanged();
} fSize = fProposalShell.getSize();
}
}); fProposalShell.setBackground(control.getDisplay().getSystemColor(SWT.COLOR_GRAY)); Color c = getBackgroundColor(control);
fProposalTable.setBackground(c); c = getForegroundColor(control);
fProposalTable.setForeground(c); fProposalTable.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) {
} public void widgetDefaultSelected(SelectionEvent e) {
insertSelectedProposalWithMask(e.stateMask);
}
}); fPopupCloser.install(fContentAssistant, fProposalTable, fAdditionalInfoController); fProposalShell.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
unregister(); // but don't dispose the shell, since we're being
// called from its disposal event!
}
}); fProposalTable.setHeaderVisible(false); addCommandSupport(fProposalTable);
} /**
* Returns the minimal required height for the proposal, may return 0 if the
* popup has not been created yet.
*
* @return the minimal height
* @since 3.3
*/
int getMinimalHeight() {
int height = 0;
if (Helper.okToUse(fProposalTable)) {
int items = fProposalTable.getItemHeight() * 10;
Rectangle trim = fProposalTable.computeTrim(0, 0, SWT.DEFAULT, items);
height = trim.height;
}
if (Helper.okToUse(fMessageText))
height += fMessageText.getSize().y + 1;
return height;
} /**
* Adds command support to the given control.
*
* @param control
* the control to watch for focus
* @since 3.2
*/
private void addCommandSupport(final Control control) {
final KeySequence commandSequence = fContentAssistant.getRepeatedInvocationKeySequence();
if (commandSequence != null && !commandSequence.isEmpty() && fContentAssistant.isRepeatedInvocationMode()) {
control.addFocusListener(new FocusListener() {
private CommandKeyListener fCommandKeyListener; public void focusGained(FocusEvent e) {
if (Helper.okToUse(control)) {
if (fCommandKeyListener == null) {
fCommandKeyListener = new CommandKeyListener(commandSequence);
fProposalTable.addKeyListener(fCommandKeyListener);
}
}
} public void focusLost(FocusEvent e) {
if (fCommandKeyListener != null) {
control.removeKeyListener(fCommandKeyListener);
fCommandKeyListener = null;
}
}
});
}
if (fAdditionalInfoController != null) {
control.addFocusListener(new FocusListener() {
private TraverseListener fTraverseListener; public void focusGained(FocusEvent e) {
if (Helper.okToUse(control)) {
if (fTraverseListener == null) {
fTraverseListener = new TraverseListener() {
public void keyTraversed(TraverseEvent event) {
if (event.detail == SWT.TRAVERSE_TAB_NEXT) {
IInformationControl iControl = fAdditionalInfoController.getCurrentInformationControl2();
if (fAdditionalInfoController.getInternalAccessor().canReplace(iControl)) {
fAdditionalInfoController.getInternalAccessor().replaceInformationControl(true);
event.doit = false;
}
}
}
};
fProposalTable.addTraverseListener(fTraverseListener);
}
}
} public void focusLost(FocusEvent e) {
if (fTraverseListener != null) {
control.removeTraverseListener(fTraverseListener);
fTraverseListener = null;
}
}
});
}
} /**
* Returns the background color to use.
*
* @param control
* the control to get the display from
* @return the background color
* @since 3.2
*/
private Color getBackgroundColor(Control control) {
Color c = fContentAssistant.getProposalSelectorBackground();
if (c == null)
c = JFaceResources.getColorRegistry().get(JFacePreferences.CONTENT_ASSIST_BACKGROUND_COLOR);
return c;
} /**
* Returns the foreground color to use.
*
* @param control
* the control to get the display from
* @return the foreground color
* @since 3.2
*/
private Color getForegroundColor(Control control) {
Color c = fContentAssistant.getProposalSelectorForeground();
if (c == null)
c = JFaceResources.getColorRegistry().get(JFacePreferences.CONTENT_ASSIST_FOREGROUND_COLOR);
return c;
} /**
* Creates the caption line under the proposal table.
*
* @since 3.2
*/
private void createMessageText() {
if (fMessageText == null) {
fMessageText = new Label(fProposalShell, SWT.RIGHT);
GridData textData = new GridData(SWT.FILL, SWT.BOTTOM, true, false);
fMessageText.setLayoutData(textData);
fMessageText.setText(fContentAssistant.getStatusMessage() + " "); //$NON-NLS-1$
if (fMessageTextFont == null) {
Font font = fMessageText.getFont();
Display display = fProposalShell.getDisplay();
FontData[] fontDatas = font.getFontData();
for (int i = 0; i < fontDatas.length; i++)
fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10);
fMessageTextFont = new Font(display, fontDatas);
}
fMessageText.setFont(fMessageTextFont);
fMessageText.setBackground(getBackgroundColor(fProposalShell));
fMessageText.setForeground(getForegroundColor(fProposalShell)); if (fContentAssistant.isRepeatedInvocationMode()) {
fMessageText.setCursor(fProposalShell.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
fMessageText.addMouseListener(new MouseAdapter() {
public void mouseUp(MouseEvent e) {
fLastCompletionOffset = fFilterOffset;
fProposalTable.setFocus();
handleRepeatedInvocation();
} public void mouseDown(MouseEvent e) {
}
});
}
}
} /*
* @since 3.1
*/
private void handleSetData(Event event) {
TableItem item = (TableItem) event.item;
int index = fProposalTable.indexOf(item); if (0 <= index && index < fFilteredProposals.length) {
ICompletionProposal current = fFilteredProposals[index]; String displayString;
StyleRange[] styleRanges = null;
if (fIsColoredLabelsSupportEnabled && current instanceof ICompletionProposalExtension6) {
StyledString styledString = ((ICompletionProposalExtension6) current).getStyledDisplayString();
displayString = styledString.getString();
styleRanges = styledString.getStyleRanges();
} else
displayString = current.getDisplayString(); item.setText(displayString);
if (fIsColoredLabelsSupportEnabled)
TableOwnerDrawSupport.storeStyleRanges(item, 0, styleRanges); item.setImage(current.getImage());
item.setData(current);
} else {
// this should not happen, but does on win32
}
} /**
* Returns the proposal selected in the proposal selector.
*
* @return the selected proposal
* @since 2.0
*/
private ICompletionProposal getSelectedProposal() {
/*
* Make sure that there is no filter runnable pending. See
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=31427
*/
if (fIsFilterPending)
fFilterRunnable.run(); // filter runnable may have hidden the proposals
if (!Helper.okToUse(fProposalTable))
return null; int i = fProposalTable.getSelectionIndex();
if (fFilteredProposals == null || i < 0 || i >= fFilteredProposals.length)
return null;
return fFilteredProposals[i];
} /**
* Takes the selected proposal and applies it.
*
* @param stateMask
* the state mask
* @since 3.2
*/
private void insertSelectedProposalWithMask(int stateMask) {
ICompletionProposal p = getSelectedProposal();
hide();
if (p != null)
insertProposal(p, (char) 0, stateMask, fContentAssistSubjectControlAdapter.getSelectedRange().x);
} /**
* Applies the given proposal at the given offset. The given character is
* the one that triggered the insertion of this proposal.
*
* @param p
* the completion proposal
* @param trigger
* the trigger character
* @param stateMask
* the state mask
* @param offset
* the offset
* @since 2.1
*/
private void insertProposal(ICompletionProposal p, char trigger, int stateMask, final int offset) { fInserting = true;
IRewriteTarget target = null;
IEditingSupport helper = new IEditingSupport() { public boolean isOriginator(DocumentEvent event, IRegion focus) {
return focus.getOffset() <= offset && focus.getOffset() + focus.getLength() >= offset;
} public boolean ownsFocusShell() {
return false;
} }; try { IDocument document = fContentAssistSubjectControlAdapter.getDocument(); if (fViewer instanceof ITextViewerExtension) {
ITextViewerExtension extension = (ITextViewerExtension) fViewer;
target = extension.getRewriteTarget();
} if (target != null)
target.beginCompoundChange(); if (fViewer instanceof IEditingSupportRegistry) {
IEditingSupportRegistry registry = (IEditingSupportRegistry) fViewer;
registry.register(helper);
} if (p instanceof ICompletionProposalExtension2 && fViewer != null) {
ICompletionProposalExtension2 e = (ICompletionProposalExtension2) p;
e.apply(fViewer, trigger, stateMask, offset);
} else if (p instanceof ICompletionProposalExtension) {
ICompletionProposalExtension e = (ICompletionProposalExtension) p;
e.apply(document, trigger, offset);
} else {
p.apply(document);
} Point selection = p.getSelection(document);
if (selection != null) {
fContentAssistSubjectControlAdapter.setSelectedRange(selection.x, selection.y);
fContentAssistSubjectControlAdapter.revealRange(selection.x, selection.y);
} IContextInformation info = p.getContextInformation();
if (info != null) { int contextInformationOffset;
if (p instanceof ICompletionProposalExtension) {
ICompletionProposalExtension e = (ICompletionProposalExtension) p;
contextInformationOffset = e.getContextInformationPosition();
} else {
if (selection == null)
selection = fContentAssistSubjectControlAdapter.getSelectedRange();
contextInformationOffset = selection.x + selection.y;
} fContentAssistant.showContextInformation(info, contextInformationOffset);
} else
fContentAssistant.showContextInformation(null, -1); } finally {
if (target != null)
target.endCompoundChange(); if (fViewer instanceof IEditingSupportRegistry) {
IEditingSupportRegistry registry = (IEditingSupportRegistry) fViewer;
registry.unregister(helper);
}
fInserting = false;
}
} /**
* Returns whether this popup has the focus.
*
* @return <code>true</code> if the popup has the focus
*/
public boolean hasFocus() {
if (Helper.okToUse(fProposalShell)) {
if ((fProposalShell.getDisplay().getActiveShell() == fProposalShell))
return true;
/*
* We have to delegate this query to the additional info controller
* as well, since the content assistant is the widget token owner
* and its closer does not know that the additional info control can
* now also take focus.
*/
if (fAdditionalInfoController != null) {
IInformationControl informationControl = fAdditionalInfoController.getCurrentInformationControl2();
if (informationControl != null && informationControl.isFocusControl())
return true;
InformationControlReplacer replacer = fAdditionalInfoController.getInternalAccessor().getInformationControlReplacer();
if (replacer != null) {
informationControl = replacer.getCurrentInformationControl2();
if (informationControl != null && informationControl.isFocusControl())
return true;
}
}
} return false;
} /**
* Hides this popup.
*/
public void hide() { unregister(); if (fViewer instanceof IEditingSupportRegistry) {
IEditingSupportRegistry registry = (IEditingSupportRegistry) fViewer;
registry.unregister(fFocusHelper);
} if (Helper.okToUse(fProposalShell)) { fContentAssistant.removeContentAssistListener(this, ContentAssistant.PROPOSAL_SELECTOR); fPopupCloser.uninstall();
fProposalShell.setVisible(false);
fProposalShell.dispose();
fProposalShell = null;
} if (fMessageTextFont != null) {
fMessageTextFont.dispose();
fMessageTextFont = null;
} if (fMessageText != null) {
fMessageText = null;
} fEmptyMessage = null; fLastCompletionOffset = -1; fContentAssistant.fireSessionEndEvent();
} /**
* Unregister this completion proposal popup.
*
* @since 3.0
*/
private void unregister() {
if (fDocumentListener != null) {
IDocument document = fContentAssistSubjectControlAdapter.getDocument();
if (document != null)
document.removeDocumentListener(fDocumentListener);
fDocumentListener = null;
}
fDocumentEvents.clear(); if (fKeyListener != null && fContentAssistSubjectControlAdapter.getControl() != null && !fContentAssistSubjectControlAdapter.getControl().isDisposed()) {
fContentAssistSubjectControlAdapter.removeKeyListener(fKeyListener);
fKeyListener = null;
} if (fLastProposal != null) {
if (fLastProposal instanceof ICompletionProposalExtension2 && fViewer != null) {
ICompletionProposalExtension2 extension = (ICompletionProposalExtension2) fLastProposal;
extension.unselected(fViewer);
}
fLastProposal = null;
} fFilteredProposals = null;
fComputedProposals = null; fContentAssistant.possibleCompletionsClosed();
} /**
* Returns whether this popup is active. It is active if the proposal
* selector is visible.
*
* @return <code>true</code> if this popup is active
*/
public boolean isActive() {
return fProposalShell != null && !fProposalShell.isDisposed();
} /**
* Initializes the proposal selector with these given proposals.
*
* @param proposals
* the proposals
* @param isFilteredSubset
* if <code>true</code>, the proposal table is not cleared, but
* the proposals that are not in the passed array are removed
* from the displayed set
*/
private void setProposals(ICompletionProposal[] proposals, boolean isFilteredSubset) {
ICompletionProposal[] oldProposals = fFilteredProposals;
ICompletionProposal oldProposal = getSelectedProposal(); // may trigger
// filtering
// and a
// reentrant
// call to
// setProposals()
if (oldProposals != fFilteredProposals) // reentrant call was first -
// abort
return; if (Helper.okToUse(fProposalTable)) {
if (oldProposal instanceof ICompletionProposalExtension2 && fViewer != null)
((ICompletionProposalExtension2) oldProposal).unselected(fViewer); if (proposals == null || proposals.length == 0) {
fEmptyProposal.fOffset = fFilterOffset;
fEmptyProposal.fDisplayString = fEmptyMessage != null ? fEmptyMessage : JFaceTextMessages.getString("CompletionProposalPopup.no_proposals"); //$NON-NLS-1$
proposals = new ICompletionProposal[] { fEmptyProposal };
} fFilteredProposals = proposals;
final int newLen = proposals.length;
if (USE_VIRTUAL) {
fProposalTable.setItemCount(newLen);
fProposalTable.clearAll();
} else {
fProposalTable.setRedraw(false);
fProposalTable.setItemCount(newLen);
TableItem[] items = fProposalTable.getItems();
for (int i = 0; i < items.length; i++) {
TableItem item = items[i];
ICompletionProposal proposal = proposals[i];
item.setText(proposal.getDisplayString());
item.setImage(proposal.getImage());
item.setData(proposal);
}
fProposalTable.setRedraw(true);
} Point currentLocation = fProposalShell.getLocation();
Point newLocation = getLocation();
if ((newLocation.x < currentLocation.x && newLocation.y == currentLocation.y) || newLocation.y < currentLocation.y)
fProposalShell.setLocation(newLocation); selectProposal(0, false);
}
} /**
* Returns the graphical location at which this popup should be made
* visible.
*
* @return the location of this popup
*/
private Point getLocation() {
int caret = fContentAssistSubjectControlAdapter.getCaretOffset();
Rectangle location = fContentAssistant.getLayoutManager().computeBoundsBelowAbove(fProposalShell, fSize == null ? fProposalShell.getSize() : fSize, caret, this);
return Geometry.getLocation(location);
} /**
* Returns the size of this completion proposal popup.
*
* @return a Point containing the size
* @since 3.0
*/
Point getSize() {
return fSize;
} /**
* Displays this popup and install the additional info controller, so that
* additional info is displayed when a proposal is selected and additional
* info is available.
*/
private void displayProposals() { if (!Helper.okToUse(fProposalShell) || !Helper.okToUse(fProposalTable))
return; if (fContentAssistant.addContentAssistListener(this, ContentAssistant.PROPOSAL_SELECTOR)) { ensureDocumentListenerInstalled(); if (fFocusHelper == null) {
fFocusHelper = new IEditingSupport() { public boolean isOriginator(DocumentEvent event, IRegion focus) {
return false; // this helper just covers the focus
// change to the proposal shell, no
// remote editions
} public boolean ownsFocusShell() {
return true;
} };
}
if (fViewer instanceof IEditingSupportRegistry) {
IEditingSupportRegistry registry = (IEditingSupportRegistry) fViewer;
registry.register(fFocusHelper);
} /*
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=52646 on GTK,
* setVisible and such may run the event loop (see also
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=47511) Since the
* user may have already canceled the popup or selected an entry
* (ESC or RETURN), we have to double check whether the table is
* still okToUse. See comments below
*/
fProposalShell.setVisible(true); // may run event loop on GTK
// transfer focus since no verify key listener can be attached
if (!fContentAssistSubjectControlAdapter.supportsVerifyKeyListener() && Helper.okToUse(fProposalShell))
fProposalShell.setFocus(); // may run event loop on GTK ?? if (fAdditionalInfoController != null && Helper.okToUse(fProposalTable)) {
fAdditionalInfoController.install(fProposalTable);
fAdditionalInfoController.handleTableSelectionChanged();
}
} else
hide();
} /**
* Installs the document listener if not already done.
*
* @since 3.2
*/
private void ensureDocumentListenerInstalled() {
if (fDocumentListener == null) {
fDocumentListener = new IDocumentListener() {
public void documentAboutToBeChanged(DocumentEvent event) {
if (!fInserting)
fDocumentEvents.add(event);
} public void documentChanged(DocumentEvent event) {
if (!fInserting)
filterProposals();
}
};
IDocument document = fContentAssistSubjectControlAdapter.getDocument();
if (document != null)
document.addDocumentListener(fDocumentListener);
}
} /*
* @see IContentAssistListener#verifyKey(VerifyEvent)
*/
public boolean verifyKey(VerifyEvent e) {
if (!Helper.okToUse(fProposalShell))
return true; char key = e.character;
if (key == 0) {
int newSelection = fProposalTable.getSelectionIndex();
int visibleRows = (fProposalTable.getSize().y / fProposalTable.getItemHeight()) - 1;
int itemCount = fProposalTable.getItemCount();
switch (e.keyCode) { case SWT.ARROW_LEFT:
case SWT.ARROW_RIGHT:
filterProposals();
return true; case SWT.ARROW_UP:
newSelection -= 1;
if (newSelection < 0)
newSelection = itemCount - 1;
break; case SWT.ARROW_DOWN:
newSelection += 1;
if (newSelection > itemCount - 1)
newSelection = 0;
break; case SWT.PAGE_DOWN:
newSelection += visibleRows;
if (newSelection >= itemCount)
newSelection = itemCount - 1;
break; case SWT.PAGE_UP:
newSelection -= visibleRows;
if (newSelection < 0)
newSelection = 0;
break;
/*
* case SWT.HOME : newSelection= 0; break;
*
* case SWT.END : newSelection= itemCount - 1; break;
*/
default:
if (e.keyCode != SWT.CAPS_LOCK && e.keyCode != SWT.MOD1 && e.keyCode != SWT.MOD2 && e.keyCode != SWT.MOD3 && e.keyCode != SWT.MOD4)
hide();
return true;
} selectProposal(newSelection, (e.stateMask & SWT.CTRL) != 0); e.doit = false;
return false; } // key != 0
switch (key) {
case 0x1B: // Esc
e.doit = false;
hide();
break; case '\n': // Ctrl-Enter on w2k
case '\r': // Enter
case '\t': // 2017年6月7日09时52分00秒 6 Add
e.doit = false;
insertSelectedProposalWithMask(e.stateMask);
break;
/*
* case '\t': e.doit= false; fProposalShell.setFocus(); return false;
*/
default:
ICompletionProposal p = getSelectedProposal();
if (p instanceof ICompletionProposalExtension) {
ICompletionProposalExtension t = (ICompletionProposalExtension) p;
char[] triggers = t.getTriggerCharacters();
if (key != 0x20 && key != '=' && key != ';' && contains(triggers, key)) {
// if (contains(triggers, key)) {
e.doit = false;
hide();
insertProposal(p, key, e.stateMask, fContentAssistSubjectControlAdapter.getSelectedRange().x);
}
}
} return true;
} /**
* Selects the entry with the given index in the proposal selector and feeds
* the selection to the additional info controller.
*
* @param index
* the index in the list
* @param smartToggle
* <code>true</code> if the smart toggle key has been pressed
* @since 2.1
*/
private void selectProposal(int index, boolean smartToggle) { ICompletionProposal oldProposal = getSelectedProposal();
if (oldProposal instanceof ICompletionProposalExtension2 && fViewer != null)
((ICompletionProposalExtension2) oldProposal).unselected(fViewer); if (fFilteredProposals == null) {
fireSelectionEvent(null, smartToggle);
return;
} ICompletionProposal proposal = fFilteredProposals[index];
if (proposal instanceof ICompletionProposalExtension2 && fViewer != null)
((ICompletionProposalExtension2) proposal).selected(fViewer, smartToggle); fireSelectionEvent(proposal, smartToggle); fLastProposal = proposal; fProposalTable.setSelection(index);
fProposalTable.showSelection();
if (fAdditionalInfoController != null)
fAdditionalInfoController.handleTableSelectionChanged();
} /**
* Fires a selection event, see {@link ICompletionListener}.
*
* @param proposal
* the selected proposal, possibly <code>null</code>
* @param smartToggle
* true if the smart toggle is on
* @since 3.2
*/
private void fireSelectionEvent(ICompletionProposal proposal, boolean smartToggle) {
fContentAssistant.fireSelectionEvent(proposal, smartToggle);
} /**
* Returns whether the given character is contained in the given array of
* characters.
*
* @param characters
* the list of characters
* @param c
* the character to look for in the list
* @return <code>true</code> if character belongs to the list
* @since 2.0
*/
private boolean contains(char[] characters, char c) { if (characters == null)
return false; for (int i = 0; i < characters.length; i++) {
if (c == characters[i])
return true;
} return false;
} /*
* @see IEventConsumer#processEvent(VerifyEvent)
*/
public void processEvent(VerifyEvent e) {
} /**
* Filters the displayed proposal based on the given cursor position and the
* offset of the original invocation of the content assistant.
*/
private void filterProposals() {
if (!fIsFilterPending) {
fIsFilterPending = true;
Control control = fContentAssistSubjectControlAdapter.getControl();
control.getDisplay().asyncExec(fFilterRunnable);
}
} /**
* Computes the subset of already computed proposals that are still valid
* for the given offset.
*
* @param offset
* the offset
* @param event
* the merged document event
* @return the set of filtered proposals
* @since 3.0
*/
private ICompletionProposal[] computeFilteredProposals(int offset, DocumentEvent event) { if (offset == fInvocationOffset && event == null) {
fIsFilteredSubset = false;
return fComputedProposals;
} if (offset < fInvocationOffset) {
fIsFilteredSubset = false;
fInvocationOffset = offset;
fContentAssistant.fireSessionRestartEvent();
fComputedProposals = computeProposals(fInvocationOffset);
return fComputedProposals;
} ICompletionProposal[] proposals;
if (offset < fFilterOffset) {
proposals = fComputedProposals;
fIsFilteredSubset = false;
} else {
proposals = fFilteredProposals;
fIsFilteredSubset = true;
} if (proposals == null) {
fIsFilteredSubset = false;
return null;
} IDocument document = fContentAssistSubjectControlAdapter.getDocument();
int length = proposals.length;
List filtered = new ArrayList(length);
for (int i = 0; i < length; i++) { if (proposals[i] instanceof ICompletionProposalExtension2) { ICompletionProposalExtension2 p = (ICompletionProposalExtension2) proposals[i];
if (p.validate(document, offset, event))
filtered.add(p); } else if (proposals[i] instanceof ICompletionProposalExtension) { ICompletionProposalExtension p = (ICompletionProposalExtension) proposals[i];
if (p.isValidFor(document, offset))
filtered.add(p); } else {
// restore original behavior
fIsFilteredSubset = false;
fInvocationOffset = offset;
fContentAssistant.fireSessionRestartEvent();
fComputedProposals = computeProposals(fInvocationOffset);
return fComputedProposals;
}
} return (ICompletionProposal[]) filtered.toArray(new ICompletionProposal[filtered.size()]);
} /**
* Requests the proposal shell to take focus.
*
* @since 3.0
*/
public void setFocus() {
if (Helper.okToUse(fProposalShell)) {
fProposalShell.setFocus();
}
} /**
* Returns <code>true</code> if <code>proposal</code> should be
* auto-inserted, <code>false</code> otherwise.
*
* @param proposal
* the single proposal that might be automatically inserted
* @return <code>true</code> if <code>proposal</code> can be inserted
* automatically, <code>false</code> otherwise
* @since 3.1
*/
private boolean canAutoInsert(ICompletionProposal proposal) {
if (fContentAssistant.isAutoInserting()) {
if (proposal instanceof ICompletionProposalExtension4) {
ICompletionProposalExtension4 ext = (ICompletionProposalExtension4) proposal;
return ext.isAutoInsertable();
}
return true; // default behavior before
// ICompletionProposalExtension4 was introduced
}
return false;
} /**
* Completes the common prefix of all proposals directly in the code. If no
* common prefix can be found, the proposal popup is shown.
*
* @return an error message if completion failed.
* @since 3.0
*/
public String incrementalComplete() {
if (Helper.okToUse(fProposalShell) && fFilteredProposals != null) {
if (fLastCompletionOffset == fFilterOffset) {
handleRepeatedInvocation();
} else {
fLastCompletionOffset = fFilterOffset;
completeCommonPrefix();
}
} else {
final Control control = fContentAssistSubjectControlAdapter.getControl(); if (fKeyListener == null)
fKeyListener = new ProposalSelectionListener(); if (!Helper.okToUse(fProposalShell) && !control.isDisposed())
fContentAssistSubjectControlAdapter.addKeyListener(fKeyListener); BusyIndicator.showWhile(control.getDisplay(), new Runnable() {
public void run() { fInvocationOffset = fContentAssistSubjectControlAdapter.getSelectedRange().x;
fFilterOffset = fInvocationOffset;
fLastCompletionOffset = fFilterOffset;
fFilteredProposals = computeProposals(fInvocationOffset); int count = (fFilteredProposals == null ? 0 : fFilteredProposals.length);
if (count == 0 && hideWhenNoProposals(false))
return; if (count == 1 && canAutoInsert(fFilteredProposals[0])) {
insertProposal(fFilteredProposals[0], (char) 0, 0, fInvocationOffset);
hide();
} else {
ensureDocumentListenerInstalled();
if (count > 0 && completeCommonPrefix())
hide();
else {
fComputedProposals = fFilteredProposals;
createProposalSelector();
setProposals(fComputedProposals, false);
displayProposals();
}
}
}
});
}
return getErrorMessage();
} /**
* Acts upon <code>fFilteredProposals</code>: if there is just one valid
* proposal, it is inserted, otherwise, the common prefix of all proposals
* is inserted into the document. If there is no common prefix, nothing
* happens and <code>false</code> is returned.
*
* @return <code>true</code> if a single proposal was inserted and the
* selector can be closed, <code>false</code> otherwise
* @since 3.0
*/
private boolean completeCommonPrefix() { // 0: insert single proposals
if (fFilteredProposals.length == 1) {
if (canAutoInsert(fFilteredProposals[0])) {
insertProposal(fFilteredProposals[0], (char) 0, 0, fFilterOffset);
hide();
return true;
}
return false;
} // 1: extract pre- and postfix from all remaining proposals
IDocument document = fContentAssistSubjectControlAdapter.getDocument(); // contains the common postfix in the case that there are any proposals
// matching our LHS
StringBuffer rightCasePostfix = null;
List rightCase = new ArrayList(); boolean isWrongCaseMatch = false; // the prefix of all case insensitive matches. This differs from the
// document
// contents and will be replaced.
CharSequence wrongCasePrefix = null;
int wrongCasePrefixStart = 0;
// contains the common postfix of all case-insensitive matches
StringBuffer wrongCasePostfix = null;
List wrongCase = new ArrayList(); for (int i = 0; i < fFilteredProposals.length; i++) {
ICompletionProposal proposal = fFilteredProposals[i]; if (!(proposal instanceof ICompletionProposalExtension3))
return false; int start = ((ICompletionProposalExtension3) proposal).getPrefixCompletionStart(fContentAssistSubjectControlAdapter.getDocument(), fFilterOffset);
CharSequence insertion = ((ICompletionProposalExtension3) proposal).getPrefixCompletionText(fContentAssistSubjectControlAdapter.getDocument(), fFilterOffset);
if (insertion == null)
insertion = TextProcessor.deprocess(proposal.getDisplayString());
try {
int prefixLength = fFilterOffset - start;
int relativeCompletionOffset = Math.min(insertion.length(), prefixLength);
String prefix = document.get(start, prefixLength);
if (!isWrongCaseMatch && insertion.toString().startsWith(prefix)) {
isWrongCaseMatch = false;
rightCase.add(proposal);
CharSequence newPostfix = insertion.subSequence(relativeCompletionOffset, insertion.length());
if (rightCasePostfix == null)
rightCasePostfix = new StringBuffer(newPostfix.toString());
else
truncatePostfix(rightCasePostfix, newPostfix);
} else if (i == 0 || isWrongCaseMatch) {
CharSequence newPrefix = insertion.subSequence(0, relativeCompletionOffset);
if (isPrefixCompatible(wrongCasePrefix, wrongCasePrefixStart, newPrefix, start, document)) {
isWrongCaseMatch = true;
wrongCasePrefix = newPrefix;
wrongCasePrefixStart = start;
CharSequence newPostfix = insertion.subSequence(relativeCompletionOffset, insertion.length());
if (wrongCasePostfix == null)
wrongCasePostfix = new StringBuffer(newPostfix.toString());
else
truncatePostfix(wrongCasePostfix, newPostfix);
wrongCase.add(proposal);
} else {
return false;
}
} else
return false;
} catch (BadLocationException e2) {
// bail out silently
return false;
} if (rightCasePostfix != null && rightCasePostfix.length() == 0 && rightCase.size() > 1)
return false;
} // 2: replace single proposals if (rightCase.size() == 1) {
ICompletionProposal proposal = (ICompletionProposal) rightCase.get(0);
if (canAutoInsert(proposal) && rightCasePostfix.length() > 0) {
insertProposal(proposal, (char) 0, 0, fInvocationOffset);
hide();
return true;
}
return false;
} else if (isWrongCaseMatch && wrongCase.size() == 1) {
ICompletionProposal proposal = (ICompletionProposal) wrongCase.get(0);
if (canAutoInsert(proposal)) {
insertProposal(proposal, (char) 0, 0, fInvocationOffset);
hide();
return true;
}
return false;
} // 3: replace post- / prefixes CharSequence prefix;
if (isWrongCaseMatch)
prefix = wrongCasePrefix;
else
prefix = ""; //$NON-NLS-1$ CharSequence postfix;
if (isWrongCaseMatch)
postfix = wrongCasePostfix;
else
postfix = rightCasePostfix; if (prefix == null || postfix == null)
return false; try {
// 4: check if parts of the postfix are already in the document
int to = Math.min(document.getLength(), fFilterOffset + postfix.length());
StringBuffer inDocument = new StringBuffer(document.get(fFilterOffset, to - fFilterOffset));
truncatePostfix(inDocument, postfix); // 5: replace and reveal
document.replace(fFilterOffset - prefix.length(), prefix.length() + inDocument.length(), prefix.toString() + postfix.toString()); fContentAssistSubjectControlAdapter.setSelectedRange(fFilterOffset + postfix.length(), 0);
fContentAssistSubjectControlAdapter.revealRange(fFilterOffset + postfix.length(), 0);
fFilterOffset += postfix.length();
fLastCompletionOffset = fFilterOffset; return false;
} catch (BadLocationException e) {
// ignore and return false
return false;
}
} /*
* @since 3.1
*/
private boolean isPrefixCompatible(CharSequence oneSequence, int oneOffset, CharSequence twoSequence, int twoOffset, IDocument document) throws BadLocationException {
if (oneSequence == null || twoSequence == null)
return true; int min = Math.min(oneOffset, twoOffset);
int oneEnd = oneOffset + oneSequence.length();
int twoEnd = twoOffset + twoSequence.length(); String one = document.get(oneOffset, min - oneOffset) + oneSequence + document.get(oneEnd, Math.min(fFilterOffset, fFilterOffset - oneEnd));
String two = document.get(twoOffset, min - twoOffset) + twoSequence + document.get(twoEnd, Math.min(fFilterOffset, fFilterOffset - twoEnd)); return one.equals(two);
} /**
* Truncates <code>buffer</code> to the common prefix of <code>buffer</code>
* and <code>sequence</code>.
*
* @param buffer
* the common postfix to truncate
* @param sequence
* the characters to truncate with
*/
private void truncatePostfix(StringBuffer buffer, CharSequence sequence) {
// find common prefix
int min = Math.min(buffer.length(), sequence.length());
for (int c = 0; c < min; c++) {
if (sequence.charAt(c) != buffer.charAt(c)) {
buffer.delete(c, buffer.length());
return;
}
} // all equal up to minimum
buffer.delete(min, buffer.length());
} /**
* Sets the message for the repetition affordance text at the bottom of the
* proposal. Only has an effect if
* {@link ContentAssistant#isRepeatedInvocationMode()} returns
* <code>true</code>.
*
* @param message
* the new caption
* @since 3.2
*/
void setMessage(String message) {
Assert.isNotNull(message);
if (isActive() && fMessageText != null)
fMessageText.setText(message + " "); //$NON-NLS-1$
} /**
* Sets the text to be displayed if no proposals are available. Only has an
* effect if {@link ContentAssistant#isShowEmptyList()} returns
* <code>true</code>.
*
* @param message
* the empty message
* @since 3.2
*/
void setEmptyMessage(String message) {
Assert.isNotNull(message);
fEmptyMessage = message;
} /**
* Enables or disables showing of the caption line. See also
* {@link #setMessage(String)}.
*
* @param show
* <code>true</code> if the status line is visible
* @since 3.2
*/
public void setStatusLineVisible(boolean show) {
if (!isActive() || show == (fMessageText != null))
return; // nothing to do if (show) {
createMessageText();
} else {
fMessageText.dispose();
fMessageText = null;
}
fProposalShell.layout();
} /**
* Informs the popup that it is being placed above the caret line instead of
* below.
*
* @param above
* <code>true</code> if the location of the popup is above the
* caret line, <code>false</code> if it is below
* @since 3.3
*/
void switchedPositionToAbove(boolean above) {
if (fAdditionalInfoController != null) {
fAdditionalInfoController.setFallbackAnchors(new Anchor[] { AbstractInformationControlManager.ANCHOR_RIGHT, AbstractInformationControlManager.ANCHOR_LEFT, above ? AbstractInformationControlManager.ANCHOR_TOP : AbstractInformationControlManager.ANCHOR_BOTTOM });
}
} /**
* Returns a new proposal selection handler.
*
* @param operationCode
* the operation code
* @return the handler
* @since 3.4
*/
IHandler createProposalSelectionHandler(int operationCode) {
return new ProposalSelectionHandler(operationCode);
} }

下载 jre 1.4 后,复制到 C:\Program Files\Java\jre1.4.2 目录下,然后在 eclipse 项目属性中 Configure Build Path -> Libraries 选项卡下

Add Library -> JRE System Library -> Alternate JRE 选择 1.4.2 版本 然后 Installed JREs... -> Add -> Standard VM -> Directory...

找到 C:\Program Files\Java\jre1.4.2 目录,其余选项会被自动完成,这时候就添加 jre 成功了。

[原][Java]eclipse 修改自动提示的更多相关文章

  1. eclipse的自动提示功能

    一般情况下按ALT+/即可提示,若想按任意字母都有提示,则可以打开eclipse的自动提示功能,打开或关闭该提示功能的步骤如下: 打开eclipse后一次点Window->Perferences ...

  2. Eclipse代码自动提示设置

    以前百度过如何设置Eclipse代码自动提示,但是本人记性不好,所以把这个方法写成一篇日志,这样以后就不用百度了,直接看自己的博客就是了,而且还增加了自己博客的点击量.以下是从各个地方看到总结的方法: ...

  3. eclipse代码自动提示,eclipse设置代码自动提示

    eclipse代码自动提示,eclipse设置代码自动提示 eclipse是很多JAVA开发者基本上都用的工具,用它可以很方便的开发JAVA代码,当编写JAVA代码时,大部分人都是按组合键[Alt+/ ...

  4. 如何设置eclipse代码自动提示功能

    如何设置eclipse代码自动提示功能 我们在刚安装完使用eclipse进行开发时,会发现没有代码提示会非常的不方便,下面小编将告诉你如何进行代码自动提示的设置. 工具/原料   eclipse 电脑 ...

  5. Eclipse设置自动提示

    Eclipse设置自动提示可通过以下方式实现, 1.运行Eclipse开发工具,在开发工具最顶端菜单栏,点击"windows"->"preferences" ...

  6. Eclipse中自动提示的方法参数都是arg0,arg1的解决方法

    Eclipse中自动提示的方法参数都是arg0,arg1,就不能根据参数名来推断参数的含义,非常不方便. 解决方法:Preferences->Java->Installed JREs,发现 ...

  7. Eclipse 代码自动提示的设置

    1. eclipse代码自动提示设置.如何配置eclipse的代码自动提示功能(同时解决自动补全变量名的问题)? 2. http://www.iteye.com/topic/1120919 [C++] ...

  8. eclipse代码自动提示设置、如何配置eclipse的代码自动提示功能(同时解决自动补全变量名的问题)?

    对于编程人员来说,要记住大量的类名或类方法的名字,着实不是一件容易的事情.如果要IDE能够自动补全代码,那将为我们编程人员带来很大帮助. eclipse代码里面的代码提示功能默认是关闭的,只有输入“. ...

  9. 设置Eclipse代码自动提示

    对于编程人员来说,要记住大量的类名或类方法的名字,着实不是一件容易的事情.如果要IDE能够自动补全代码,那将为我们编程人员带来很大帮助. Eclipse代码里面的代码提示功能默认是关闭的,只有输入“. ...

随机推荐

  1. Redis之数据备份与恢复

    Redis 数据备份与恢复 Redis SAVE 命令用于创建当前数据库的备份. 语法 redis Save 命令基本语法如下: redis 127.0.0.1:6379> SAVE 实例 re ...

  2. JVM的异常处理

    异常处理的两大组成要素:抛出异常和捕获异常.这两大要素共同实现程序控制流的非正常转移. 抛出异常分为:显式和隐式两种. 显式抛异常的主题是应用程序,它指的是在程序中使用 “throw”  关键字.手动 ...

  3. node scripts/install.js 停顿解决办法

    参考:node-sass 安装卡在 node scripts/install.js 解决办法 在安装hexo的时候,运行: npm install hexo-cli -g 卡死在了 node scri ...

  4. 2015-9-13 NOIP模拟赛 by hzwer

    好老的题了,但是还是很有做头的. 总结 不吸氧看来确实是没法用stl的啊(set常数太大了,开O2也没过) SPFA没认真学,觉得有堆优化Dijkstra就天下无敌了,今天负边权教我做人 于是苦逼的只 ...

  5. UVa 12549 机器人警卫(最小点覆盖)

    https://vjudge.net/problem/UVA-12549 题意: 在一个Y行X列的网格里有空地(.),重要位置(*)和障碍物(#),用最少的机器人看守所有重要位置,每个机器人要放在一个 ...

  6. python 将一个列表乱序

    import random nums = [, , , , , , ] random.shuffle(nums) print(nums)

  7. CentOS6.4x86EngCustomize120g__20160307.rar

    安装的镜像包: CentOS-6.4-i386-bin-DVD1to2(CentOS-6.4-i386-bin-DVD1.iso / CentOS-6.4-i386-bin-DVD2.iso) 1. ...

  8. 【Python】xlrd,NotImplementedError-formatting_info=True not yet implemented

    前言 Python需要读取Excel(.xls..xlsx)时通常使用xlrd模块:如果要对其内容进行编辑的话稍稍有些麻烦,通常的做法是使用xlutils的copy模块对原文件进行复制,然后保存成新的 ...

  9. OOP、AOP 、IoC和DI、ORM 概念

    OOP 面向对象编程(Object Oriented Programming) OOP引入封装.继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合. AOP 面向切面编程Aspect ...

  10. xtrabackup备份之增量备份(二)

    测试了差不多一周的xtrabackup,本篇主要聊一下xtrabackup的增量备份.我一开始不是很了解,为什么每周都需要做全备份,每天都需要做增量备份,现在想想这个和技术无关.但是有一个新问题,如果 ...