parent
37c543ba48
commit
0900a62113
|
@ -10,9 +10,9 @@ import { List } from '../../../../base/browser/ui/list/listWidget.js';
|
|||
import { ResizableHTMLElement } from '../../../../base/browser/ui/resizable/resizable.js';
|
||||
import { SimpleCompletionItem } from './simpleCompletionItem.js';
|
||||
import { LineContext, SimpleCompletionModel } from './simpleCompletionModel.js';
|
||||
import { SimpleSuggestWidgetItemRenderer, type ISimpleSuggestWidgetFontInfo } from './simpleSuggestWidgetRenderer.js';
|
||||
import { getAriaId, SimpleSuggestWidgetItemRenderer, type ISimpleSuggestWidgetFontInfo } from './simpleSuggestWidgetRenderer.js';
|
||||
import { TimeoutTimer } from '../../../../base/common/async.js';
|
||||
import { Emitter, Event } from '../../../../base/common/event.js';
|
||||
import { Emitter, Event, PauseableEmitter } from '../../../../base/common/event.js';
|
||||
import { MutableDisposable, Disposable } from '../../../../base/common/lifecycle.js';
|
||||
import { clamp } from '../../../../base/common/numbers.js';
|
||||
import { localize } from '../../../../nls.js';
|
||||
|
@ -68,7 +68,9 @@ export class SimpleSuggestWidget extends Disposable {
|
|||
private _forceRenderingAbove: boolean = false;
|
||||
private _preference?: WidgetPositionPreference;
|
||||
private readonly _pendingLayout = this._register(new MutableDisposable());
|
||||
|
||||
// private _currentSuggestionDetails?: CancelablePromise<void>;
|
||||
private _focusedItem?: SimpleCompletionItem;
|
||||
private _ignoreFocusEvents: boolean = false;
|
||||
readonly element: ResizableHTMLElement;
|
||||
private readonly _messageElement: HTMLElement;
|
||||
private readonly _listElement: HTMLElement;
|
||||
|
@ -83,6 +85,8 @@ export class SimpleSuggestWidget extends Disposable {
|
|||
readonly onDidHide: Event<this> = this._onDidHide.event;
|
||||
private readonly _onDidShow = this._register(new Emitter<this>());
|
||||
readonly onDidShow: Event<this> = this._onDidShow.event;
|
||||
private readonly _onDidFocus = new PauseableEmitter<ISimpleSelectedSuggestion>();
|
||||
readonly onDidFocus: Event<ISimpleSelectedSuggestion> = this._onDidFocus.event;
|
||||
|
||||
get list(): List<SimpleCompletionItem> { return this._list; }
|
||||
|
||||
|
@ -206,6 +210,7 @@ export class SimpleSuggestWidget extends Disposable {
|
|||
|
||||
this._register(this._list.onMouseDown(e => this._onListMouseDownOrTap(e)));
|
||||
this._register(this._list.onTap(e => this._onListMouseDownOrTap(e)));
|
||||
this._register(this._list.onDidChangeFocus(e => this._onListFocus(e)));
|
||||
this._register(this._list.onDidChangeSelection(e => this._onListSelection(e)));
|
||||
this._register(configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('editor.suggest.showIcons')) {
|
||||
|
@ -214,6 +219,67 @@ export class SimpleSuggestWidget extends Disposable {
|
|||
}));
|
||||
}
|
||||
|
||||
private _onListFocus(e: IListEvent<SimpleCompletionItem>): void {
|
||||
if (this._ignoreFocusEvents) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._state === State.Details) {
|
||||
// This can happen when focus is in the details-panel and when
|
||||
// arrow keys are pressed to select next/prev items
|
||||
this._setState(State.Open);
|
||||
}
|
||||
|
||||
if (!e.elements.length) {
|
||||
// if (this._currentSuggestionDetails) {
|
||||
// this._currentSuggestionDetails.cancel();
|
||||
// this._currentSuggestionDetails = undefined;
|
||||
// this._focusedItem = undefined;
|
||||
// }
|
||||
this._clearAriaActiveDescendant();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._completionModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
// this._ctxSuggestWidgetHasFocusedSuggestion.set(true);
|
||||
const item = e.elements[0];
|
||||
const index = e.indexes[0];
|
||||
|
||||
if (item !== this._focusedItem) {
|
||||
|
||||
// this._currentSuggestionDetails?.cancel();
|
||||
// this._currentSuggestionDetails = undefined;
|
||||
|
||||
this._focusedItem = item;
|
||||
|
||||
this._list.reveal(index);
|
||||
const id = getAriaId(index);
|
||||
const node = dom.getActiveWindow().document.activeElement;
|
||||
if (node && id) {
|
||||
node.setAttribute('aria-haspopup', 'true');
|
||||
node.setAttribute('aria-autocomplete', 'list');
|
||||
node.setAttribute('aria-activedescendant', id);
|
||||
} else {
|
||||
this._clearAriaActiveDescendant();
|
||||
}
|
||||
}
|
||||
// emit an event
|
||||
this._onDidFocus.fire({ item, index, model: this._completionModel });
|
||||
}
|
||||
|
||||
private _clearAriaActiveDescendant(): void {
|
||||
const node = dom.getActiveWindow().document.activeElement;
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
node.setAttribute('aria-haspopup', 'false');
|
||||
node.setAttribute('aria-autocomplete', 'both');
|
||||
node.removeAttribute('aria-activedescendant');
|
||||
}
|
||||
|
||||
private _cursorPosition?: { top: number; left: number; height: number };
|
||||
|
||||
setCompletionModel(completionModel: SimpleCompletionModel) {
|
||||
|
|
|
@ -14,7 +14,7 @@ import { DisposableStore } from '../../../../base/common/lifecycle.js';
|
|||
import { ThemeIcon } from '../../../../base/common/themables.js';
|
||||
|
||||
export function getAriaId(index: number): string {
|
||||
return `simple-suggest-aria-id:${index}`;
|
||||
return `simple-suggest-aria-id-${index}`;
|
||||
}
|
||||
|
||||
export interface ISimpleSuggestionTemplateData {
|
||||
|
|
Loading…
Reference in New Issue