diff options
author | teicher | 2003-12-09 14:46:48 +0000 |
---|---|---|
committer | teicher | 2003-12-09 14:46:48 +0000 |
commit | 57efe0e5c12d39e6a8096d247fe3d5d573859c02 (patch) | |
tree | 23c116d71f256a23b3072855e3e4db52e5f35d99 | |
parent | 6327693adabb12d83b2a7804296333c75c44b7b9 (diff) | |
download | eclipse.platform.text-57efe0e5c12d39e6a8096d247fe3d5d573859c02.tar.gz eclipse.platform.text-57efe0e5c12d39e6a8096d247fe3d5d573859c02.tar.xz eclipse.platform.text-57efe0e5c12d39e6a8096d247fe3d5d573859c02.zip |
- makes linked positions robust against cases where the linked ui was not set up properlyv20031209a
- removes leak (shell listener in LinkedUIControl)
- better context info handling
2 files changed, 151 insertions, 26 deletions
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/ContentAssistant.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/ContentAssistant.java index b8fda8885c9..60670c2c9bf 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/ContentAssistant.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/ContentAssistant.java @@ -1097,18 +1097,18 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt switch (type) { case CONTEXT_SELECTOR: case PROPOSAL_SELECTOR: - if (fContentAssistSubject instanceof IWidgetTokenOwner) { - IWidgetTokenOwner owner= (IWidgetTokenOwner)fContentAssistSubject; - return owner.requestWidgetToken(this); - } else if (fContentAssistSubject instanceof IWidgetTokenOwnerExtension) { + if (fContentAssistSubject instanceof IWidgetTokenOwnerExtension) { IWidgetTokenOwnerExtension extension= (IWidgetTokenOwnerExtension)fContentAssistSubject; return extension.requestWidgetToken(this, WIDGET_PRIORITY); - } else if (fViewer instanceof IWidgetTokenOwner) { - IWidgetTokenOwner owner= (IWidgetTokenOwner) fViewer; + } else if (fContentAssistSubject instanceof IWidgetTokenOwner) { + IWidgetTokenOwner owner= (IWidgetTokenOwner)fContentAssistSubject; return owner.requestWidgetToken(this); } else if (fViewer instanceof IWidgetTokenOwnerExtension) { IWidgetTokenOwnerExtension extension= (IWidgetTokenOwnerExtension) fViewer; return extension.requestWidgetToken(this, WIDGET_PRIORITY); + } else if (fViewer instanceof IWidgetTokenOwner) { + IWidgetTokenOwner owner= (IWidgetTokenOwner) fViewer; + return owner.requestWidgetToken(this); } } return true; @@ -1141,7 +1141,8 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt fCloser.install(); fContentAssistSubjectAdapter.setEventConsumer(fInternalListener); installKeyListener(); - } + } else + promoteKeyListener(); return true; } @@ -1149,6 +1150,19 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt } /** + * Repromotes the keylistener to the first position, using + * prependVerifyKeyListener. This ensures no other instance is + * filtering away the keystrokes underneath, if we've been up for a + * while (e.g. when the context info is showing. + * + * @since 3.0 + */ + private void promoteKeyListener() { + uninstallVerifyKeyListener(); + installKeyListener(); + } + + /** * Installs a key listener on the text viewer's widget. */ private void installKeyListener() { @@ -1240,6 +1254,7 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt * @see IContentAssist#showPossibleCompletions */ public String showPossibleCompletions() { + promoteKeyListener(); return fProposalPopup.showProposals(false); } @@ -1254,6 +1269,7 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt * @see IContentAssist#showContextInformation */ public String showContextInformation() { + promoteKeyListener(); if (fContextInfoPopup != null) return fContextInfoPopup.showContextProposals(false); else diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/ContextInformationPopup.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/ContextInformationPopup.java index 68d46876661..55312ac2649 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/ContextInformationPopup.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/ContextInformationPopup.java @@ -12,6 +12,7 @@ package org.eclipse.jface.text.contentassist; +import java.util.Iterator; import java.util.Stack; import org.eclipse.swt.SWT; @@ -64,6 +65,18 @@ class ContextInformationPopup implements IContentAssistListener { public IContextInformation fInformation; public IContextInformationValidator fValidator; public IContextInformationPresenter fPresenter; + + /* + * @see java.lang.Object#equals(java.lang.Object) + * @since 3.0 + */ + public boolean equals(Object obj) { + if (obj instanceof ContextFrame) { + ContextFrame frame= (ContextFrame) obj; + return fInformation.equals(frame.fInformation) && fBeginOffset == frame.fBeginOffset; + } + return super.equals(obj); + } } private ITextViewer fViewer; @@ -102,6 +115,14 @@ class ContextInformationPopup implements IContentAssistListener { private SelectionListener fTextWidgetSelectionListener; /** + * The last removed context frame is remembered in order to not re-query the + * user about which context should be used. + * + * @since 3.0 + */ + private ContextFrame fLastContext= null; + + /** * Creates a new context information popup. * * @param contentAssistant the content assist for computing the context information @@ -143,10 +164,44 @@ class ContextInformationPopup implements IContentAssistListener { int count = (contexts == null ? 0 : contexts.length); if (count == 1) { - // Show context information directly - internalShowContextInfo(contexts[0], position); + ContextFrame frame= createContextFrame(contexts[0], position); + if (isDuplicate(frame)) + validateContextInformation(); + else + // Show context information directly + internalShowContextInfo(frame); } else if (count > 0) { + + // if any of the proposed context matches the any of the contexts on the stack, + // assume that one (so, if context info is invoked repeatedly, the current + // info is kept) + for (int i= 0; i < contexts.length; i++) { + IContextInformation info= contexts[i]; + ContextFrame frame= createContextFrame(info, position); + + // check top of stack and stored context + if (isDuplicate(frame)) { + validateContextInformation(); + return; + } + + if (isLastFrame(frame)) { + internalShowContextInfo(frame); + return; + } + + // also check all other contexts + for (Iterator it= fContextFrameStack.iterator(); it.hasNext(); ) { + ContextFrame stackFrame= (ContextFrame) it.next(); + if (stackFrame.equals(frame)) { + validateContextInformation(); + return; + } + } + } + + // otherwise: // Precise context must be selected if (fLineDelimiter == null) @@ -177,7 +232,11 @@ class ContextInformationPopup implements IContentAssistListener { Control control= fContentAssistSubjectAdapter.getControl(); BusyIndicator.showWhile(control.getDisplay(), new Runnable() { public void run() { - internalShowContextInfo(info, position); + ContextFrame frame= createContextFrame(info, position); + if (isDuplicate(frame)) + validateContextInformation(); + else + internalShowContextInfo(frame); hideContextSelector(); } }); @@ -186,13 +245,26 @@ class ContextInformationPopup implements IContentAssistListener { /** * Displays the given context information for the given offset. * + * @param frame the context frame tod display, or <code>null</code> + * @since 3.0 + */ + private void internalShowContextInfo(ContextFrame frame) { + if (frame != null) { + fContextFrameStack.push(frame); + if (fContextFrameStack.size() == 1) + fLastContext= null; + internalShowContextFrame(frame, fContextFrameStack.size() == 1); + } + } + + /** + * Creates a context frame for the given offset. + * * @param info the context information * @param position the offset - * @since 2.0 + * @since 3.0 */ - - private void internalShowContextInfo(IContextInformation information, int offset) { - + private ContextFrame createContextFrame(IContextInformation information, int offset) { IContextInformationValidator validator= fContentAssistSubjectAdapter.getContextInformationValidator(fContentAssistant, offset); if (validator != null) { @@ -204,11 +276,40 @@ class ContextInformationPopup implements IContentAssistListener { current.fVisibleOffset= fContentAssistSubjectAdapter.getWidgetSelectionRange().x - (offset - current.fBeginOffset); current.fValidator= validator; current.fPresenter= fContentAssistSubjectAdapter.getContextInformationPresenter(fContentAssistant, offset); - - fContextFrameStack.push(current); - - internalShowContextFrame(current, fContextFrameStack.size() == 1); + return current; } + + return null; + } + + /** + * Compares <code>frame</code> with the top of the stack, returns <code>true</code> + * if the frames are the same. + * + * @param frame the frame to check + * @return <code>true</code> if <code>frame</code> matches the top of the stack + * @since 3.0 + */ + private boolean isDuplicate(ContextFrame frame) { + if (frame == null) + return false; + if (fContextFrameStack.isEmpty()) + return false; + // stack not empty + ContextFrame top= (ContextFrame) fContextFrameStack.peek(); + return frame.equals(top); + } + + /** + * Compares <code>frame</code> with most recently removed context frame, returns <code>true</code> + * if the frames are the same. + * + * @param frame the frame to check + * @return <code>true</code> if <code>frame</code> matches the most recently removed + * @since 3.0 + */ + private boolean isLastFrame(ContextFrame frame) { + return frame != null && frame.equals(fLastContext); } /** @@ -325,7 +426,7 @@ class ContextInformationPopup implements IContentAssistListener { int size= fContextFrameStack.size(); if (size > 0) { - fContextFrameStack.pop(); + fLastContext= (ContextFrame) fContextFrameStack.pop(); -- size; } @@ -411,7 +512,7 @@ class ContextInformationPopup implements IContentAssistListener { return; int position= fContentAssistSubjectAdapter.getSelectedRange().x; - internalShowContextInfo(fContextSelectorInput[i], position); + internalShowContextInfo(createContextFrame(fContextSelectorInput[i], position)); } /** @@ -659,13 +760,21 @@ class ContextInformationPopup implements IContentAssistListener { private ContextFrame fFrame= (ContextFrame) fContextFrameStack.peek(); public void run() { - if (Helper.okToUse(fContextInfoPopup) && fFrame == fContextFrameStack.peek()) { + // only do this if no other frames have been added in between + if (!fContextFrameStack.isEmpty() && fFrame == fContextFrameStack.peek()) { int offset= fContentAssistSubjectAdapter.getSelectedRange().x; - if (fFrame.fValidator == null || !fFrame.fValidator.isContextInformationValid(offset)) { - hideContextInfoPopup(); - } else if (fFrame.fPresenter != null && fFrame.fPresenter.updatePresentation(offset, fTextPresentation)) { - TextPresentation.applyTextPresentation(fTextPresentation, fContextInfoText); - resize(); + + // iterate all contexts on the stack + while (Helper.okToUse(fContextInfoPopup) && !fContextFrameStack.isEmpty()) { + ContextFrame top= (ContextFrame) fContextFrameStack.peek(); + if (top.fValidator == null || !top.fValidator.isContextInformationValid(offset)) { + hideContextInfoPopup(); // loop variant: reduces the number of contexts on the stack + } else if (top.fPresenter != null && top.fPresenter.updatePresentation(offset, fTextPresentation)) { + TextPresentation.applyTextPresentation(fTextPresentation, fContextInfoText); + resize(); + break; + } else + break; } } } |