From 10ead5ff267811da4b2a2cade7b884475825b17c Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 8 Feb 2016 10:48:34 +0100 Subject: [PATCH] suggest: next, previous --- src/vs/base/browser/ui/list/listWidget.ts | 42 +++++ .../contrib/suggest/browser/suggestWidget.ts | 158 +++++++++--------- 2 files changed, 123 insertions(+), 77 deletions(-) diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index 0cd16aee3ad..b99cf0818df 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -109,6 +109,18 @@ class Trait implements IDisposable { return this.indexes.some(i => i === index); } + next(n: number): void { + let index = this.indexes.length ? this.indexes[0] : 0; + index = Math.min(index + n, this.indexes.length); + this.set(index); + } + + previous(n: number): void { + let index = this.indexes.length ? this.indexes[0] : this.indexes.length - 1; + index = Math.max(index - n, 0); + this.set(index); + } + wrapRenderer(renderer: IRenderer): IRenderer> { return new TraitRenderer(this, renderer); } @@ -202,11 +214,41 @@ export class List implements IDisposable { indexes.forEach(i => this.view.splice(i, 1, this.view.element(i))); } + selectNext(n = 1, loop = false): void { + if (this.length === 0) return; + const selection = this.selection.get(); + let index = selection.length > 0 ? selection[0] + n : 0; + this.selection.set(loop ? index % this.length : Math.min(index, this.length - 1)); + } + + selectPrevious(n = 1, loop = false): void { + if (this.length === 0) return; + const selection = this.selection.get(); + let index = selection.length > 0 ? selection[0] - n : 0; + if (loop && index < 0) index = this.length + (index % this.length); + this.selection.set(Math.max(index, 0)); + } + setFocus(...indexes: number[]): void { indexes = indexes.concat(this.focus.set(...indexes)); indexes.forEach(i => this.view.splice(i, 1, this.view.element(i))); } + focusNext(n = 1, loop = false): void { + if (this.length === 0) return; + const focus = this.focus.get(); + let index = focus.length > 0 ? focus[0] + n : 0; + this.focus.set(loop ? index % this.length : Math.min(index, this.length - 1)); + } + + focusPrevious(n = 1, loop = false): void { + if (this.length === 0) return; + const focus = this.focus.get(); + let index = focus.length > 0 ? focus[0] - n : 0; + if (loop && index < 0) index = this.length + (index % this.length); + this.focus.set(Math.max(index, 0)); + } + getFocus(): T[] { return this.focus.get().map(i => this.view.element(i)); } diff --git a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts index 71e570496b3..1bd2e2f9cd1 100644 --- a/src/vs/editor/contrib/suggest/browser/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/browser/suggestWidget.ts @@ -426,7 +426,7 @@ export class SuggestWidget implements EditorBrowser.IContentWidget, IDisposable private suggestionSupportsAutoAccept: IKeybindingContextKey; private loadingTimeout: number; private currentSuggestionDetails: TPromise; - private oldFocus: CompletionItem; + private focusedItem: CompletionItem; private completionModel: CompletionModel; private telemetryData: ITelemetryData; @@ -453,7 +453,7 @@ export class SuggestWidget implements EditorBrowser.IContentWidget, IDisposable @IInstantiationService instantiationService: IInstantiationService ) { this.isAuto = false; - this.oldFocus = null; + this.focusedItem = null; this.suggestionSupportsAutoAccept = keybindingService.createKey(CONTEXT_SUGGESTION_SUPPORTS_ACCEPT_ON_KEY, true); this.telemetryData = null; @@ -484,7 +484,7 @@ export class SuggestWidget implements EditorBrowser.IContentWidget, IDisposable SuggestRegistry.onDidChange(() => this.onModelModeChanged()), // editor.addListener2(EditorCommon.EventType.EditorTextBlur, () => this.onEditorBlur()), this.list.onSelectionChange(e => this.onListSelection(e)), - // this.list.addListener2('focus', e => this.onTreeFocus(e)), + this.list.onFocusChange(e => this.onListFocus(e)), this.editor.addListener2(EditorCommon.EventType.CursorSelectionChanged, () => this.onCursorSelectionChanged()), this.model.onDidTrigger(e => this.onDidTrigger(e)), this.model.onDidSuggest(e => this.onDidSuggest(e)), @@ -533,35 +533,47 @@ export class SuggestWidget implements EditorBrowser.IContentWidget, IDisposable }, 0); } - // private onTreeFocus(e: Tree.IFocusEvent): void { - // const focus = e.focus; - // const payload = e.payload; + private onListFocus(e: IFocusChangeEvent): void { + if (!e.elements.length) { + return; + } - // if (focus instanceof CompletionItem) { - // this.resolveDetails(focus); - // this.suggestionSupportsAutoAccept.set(!(focus).suggestion.noAutoAccept); - // } + const item = e.elements[0]; - // const elementsToRefresh: any[] = []; + if (item === this.focusedItem) { + return; + } - // if (this.oldFocus) { - // elementsToRefresh.push(this.oldFocus); - // } + const index = e.indexes[0]; + // const payload = e.payload; - // if (focus) { - // elementsToRefresh.push(focus); - // } + this.resolveDetails(item, index); + this.suggestionSupportsAutoAccept.set(!(item).suggestion.noAutoAccept); - // this.oldFocus = focus; + if (this.focusedItem) { + const index = this.completionModel.items.indexOf(this.focusedItem); + if (index > -1) this.list.splice(index, 1, this.focusedItem); + this.focusedItem = null; + } - // this.list.refreshAll(elementsToRefresh).done(() => { - // this.updateWidgetHeight(); + if (item) { + this.focusedItem = item; + this.list.splice(index, 1, item); + this.list.setFocus(index); + } - // if (focus) { - // return this.list.reveal(focus, (payload && payload.firstSuggestion) ? 0 : null); - // } - // }, onUnexpectedError); - // } + this.updateWidgetHeight(); + + if (item) { + this.list.reveal(index); + } + + // this.list.refreshAll(elementsToRefresh).done(() => { + // if (item) { + // return this.list.reveal(item, (payload && payload.firstSuggestion) ? 0 : null); + // } + // }, onUnexpectedError); + } private onModelModeChanged(): void { const model = this.editor.getModel(); @@ -737,26 +749,28 @@ export class SuggestWidget implements EditorBrowser.IContentWidget, IDisposable } } - // private resolveDetails(item: CompletionItem): void { - // if (!item) { - // return; - // } + private resolveDetails(item: CompletionItem, index: number): void { + if (this.currentSuggestionDetails) { + this.currentSuggestionDetails.cancel(); + } - // if (this.currentSuggestionDetails) { - // this.currentSuggestionDetails.cancel(); - // } + this.currentSuggestionDetails = item.resolveDetails( + this.editor.getModel().getAssociatedResource(), + this.model.getRequestPosition() || this.editor.getPosition() + ); - // this.currentSuggestionDetails = item.resolveDetails( - // this.editor.getModel().getAssociatedResource(), - // this.model.getRequestPosition() || this.editor.getPosition() - // ); + this.currentSuggestionDetails.then(() => { + this.currentSuggestionDetails = undefined; - // this.currentSuggestionDetails.then(() => { - // this.currentSuggestionDetails = undefined; - // return this.list.refresh(item).then(() => this.updateWidgetHeight()); - // }) - // .done(null, err => !isPromiseCanceledError(err) && onUnexpectedError(err)); - // } + if (item === this.focusedItem) { + this.list.splice(index, 1, item); + this.list.setFocus(index); + this.updateWidgetHeight(); + } + }, + err => !isPromiseCanceledError(err) && onUnexpectedError(err) + ); + } public selectNextPage(): boolean { return false; @@ -775,23 +789,18 @@ export class SuggestWidget implements EditorBrowser.IContentWidget, IDisposable } public selectNext(): boolean { - return false; - // switch (this.state) { - // case State.Hidden: - // return false; - // case State.Details: - // this.details.scrollDown(); - // return true; - // case State.Loading: - // return !this.isAuto; - // default: - // const focus = this.list.getFocus(); - // this.list.focusNext(1); - // if (focus === this.list.getFocus()) { - // this.list.focusFirst(); - // } - // return true; - // } + switch (this.state) { + case State.Hidden: + return false; + case State.Details: + this.details.scrollDown(); + return true; + case State.Loading: + return !this.isAuto; + default: + this.list.focusNext(1, true); + return true; + } } public selectPreviousPage(): boolean { @@ -811,23 +820,18 @@ export class SuggestWidget implements EditorBrowser.IContentWidget, IDisposable } public selectPrevious(): boolean { - return false; - // switch (this.state) { - // case State.Hidden: - // return false; - // case State.Details: - // this.details.scrollUp(); - // return true; - // case State.Loading: - // return !this.isAuto; - // default: - // const focus = this.list.getFocus(); - // this.list.focusPrevious(1); - // if (focus === this.list.getFocus()) { - // this.list.focusLast(); - // } - // return true; - // } + switch (this.state) { + case State.Hidden: + return false; + case State.Details: + this.details.scrollUp(); + return true; + case State.Loading: + return !this.isAuto; + default: + this.list.focusPrevious(1, true); + return true; + } } public acceptSelectedSuggestion(): boolean { @@ -951,7 +955,7 @@ export class SuggestWidget implements EditorBrowser.IContentWidget, IDisposable this.state = null; this.suggestionSupportsAutoAccept = null; this.currentSuggestionDetails = null; - this.oldFocus = null; + this.focusedItem = null; this.telemetryData = null; this.telemetryService = null; this.telemetryTimer = null; -- GitLab