Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding accessibility help for verbose hover #212783

Merged
merged 33 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
36a5ff6
adding code in order to provide accessibility help for the hover
aiday-mar May 15, 2024
34513de
adding the description of the possible commands that can be used
aiday-mar May 15, 2024
04cb337
reusing the method
aiday-mar May 15, 2024
a1851bd
joining the content and changing the text in the help view
aiday-mar May 15, 2024
cf2cfe0
Merge branch 'main' into whispering-gorilla
aiday-mar May 15, 2024
9a358bf
polishing the code
aiday-mar May 15, 2024
f07cd63
removing the question mark
aiday-mar May 15, 2024
31ea768
changing the import
aiday-mar May 15, 2024
24062b1
removing the setting ID from imports
aiday-mar May 16, 2024
cb92438
adding code in order to update when the hover updates
aiday-mar May 16, 2024
fa6bc6c
adding methods to service
aiday-mar May 17, 2024
a0c67a5
adding code in order to dispose the accessible hover view
aiday-mar May 21, 2024
4b77920
fixing bug
aiday-mar May 21, 2024
42a7702
polishing the code
aiday-mar May 21, 2024
32120f1
checking that action not supported for the early return
aiday-mar May 21, 2024
676ce75
using disposable store instead
aiday-mar May 21, 2024
c037269
using the appropriate string
aiday-mar May 21, 2024
9c71082
polishing the code
aiday-mar May 22, 2024
052aa39
Merge branch 'main' into whispering-gorilla
aiday-mar May 23, 2024
1f450dd
using instead the type help and the resolved keybindings
aiday-mar May 23, 2024
1b60028
hiding also on the `onDidBlurEditorWidget` firing
aiday-mar May 23, 2024
12f0cf6
Revert "using instead the type help and the resolved keybindings"
meganrogge May 23, 2024
592fca0
use hover accessible view, provide custom help
meganrogge May 23, 2024
bcd5d95
Revert "Revert "using instead the type help and the resolved keybindi…
meganrogge May 23, 2024
992e464
add HoverAccessibilityHelp, BaseHoverAccessibleViewProvider
meganrogge May 23, 2024
82b9f49
polishing the code
aiday-mar May 24, 2024
039459e
Merge branch 'main' into whispering-gorilla
aiday-mar May 24, 2024
107b1ab
polishing the code
aiday-mar May 24, 2024
80870b3
provide content at a specific index from the hover accessibility help…
aiday-mar May 24, 2024
c2b2b78
introducing method _initializeOptions
aiday-mar May 24, 2024
56f21d5
using readonly where possible
aiday-mar May 24, 2024
b861568
using public everywhere
aiday-mar May 24, 2024
09f5d26
using a getter for the actions
aiday-mar May 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/vs/editor/contrib/hover/browser/contentHoverController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,10 @@ export class ContentHoverController extends Disposable implements IHoverWidget {
this._markdownHoverParticipant?.updateFocusedMarkdownHoverPartVerbosityLevel(action);
}

public isFocusOnMarkdownHoverWhichSupportsVerbosityAction(action: HoverVerbosityAction): boolean {
return this._markdownHoverParticipant?.isFocusOnMarkdownHoverWhichSupportsVerbosityAction(action) ?? false;
}

public getWidgetContent(): string | undefined {
const node = this._widget.getDomNode();
if (!node.textContent) {
Expand Down
97 changes: 75 additions & 22 deletions src/vs/editor/contrib/hover/browser/hoverAccessibleViews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,101 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { localize } from 'vs/nls';
import { format } from 'vs/base/common/strings';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { HoverController } from 'vs/editor/contrib/hover/browser/hoverController';
import { AccessibleViewType, AccessibleViewProviderId } from 'vs/platform/accessibility/browser/accessibleView';
import { AccessibleViewType, AccessibleViewProviderId, AdvancedContentProvider, IAccessibleViewContentProvider, IAccessibleViewOptions } from 'vs/platform/accessibility/browser/accessibleView';
import { IAccessibleViewImplentation } from 'vs/platform/accessibility/browser/accessibleViewRegistry';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IHoverService } from 'vs/platform/hover/browser/hover';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { HoverVerbosityAction } from 'vs/editor/common/languages';
import { DECREASE_HOVER_VERBOSITY_ACTION_ID, INCREASE_HOVER_VERBOSITY_ACTION_ID } from 'vs/editor/contrib/hover/browser/hoverActionIds';
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';

namespace HoverAccessibilityHelpNLS {
export const intro = localize('intro', "The hover widget is focused. Press the Tab key to cycle through the hover parts.");
export const increaseVerbosity = localize('increaseVerbosity', "- The focused hover part verbosity level can be increased ({0}).");
export const increaseVerbosityNoKb = localize('increaseVerbosityNoKb', "- The focused hover part verbosity level can be increased, which is currently not triggerable via keybinding.");
export const decreaseVerbosity = localize('decreaseVerbosity', "- The focused hover part verbosity level can be decreased ({0}).");
export const decreaseVerbosityNoKb = localize('decreaseVerbosityNoKb', "- The focused hover part verbosity level can be decreased, which is currently not triggerable via keybinding.");
}

export class HoverAccessibleView implements IAccessibleViewImplentation {

readonly type = AccessibleViewType.View;
readonly priority = 95;
readonly name = 'hover';
readonly when = EditorContextKeys.hoverFocused;
getProvider(accessor: ServicesAccessor) {

getProvider(accessor: ServicesAccessor): AdvancedContentProvider | undefined {
const codeEditorService = accessor.get(ICodeEditorService);
const editor = codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor();
const editorHoverContent = editor ? HoverController.get(editor)?.getWidgetContent() ?? undefined : undefined;
if (!editor || !editorHoverContent) {
return;
let codeEditor = codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor();
if (!codeEditor) {
return undefined;
}
return {
id: AccessibleViewProviderId.Hover,
verbositySettingKey: 'accessibility.verbosity.hover',
provideContent() { return editorHoverContent; },
onClose() {
HoverController.get(editor)?.focus();
},
options: {
language: editor?.getModel()?.getLanguageId() ?? 'typescript',
type: AccessibleViewType.View
}
};
return accessor.get(IInstantiationService).createInstance(HoverAccessibilityHelpProvider, codeEditor);
}
}

export class HoverAccessibilityHelpProvider implements IAccessibleViewContentProvider {

public readonly options: IAccessibleViewOptions;
public readonly id = AccessibleViewProviderId.Hover;
public readonly verbositySettingKey = AccessibilityVerbositySettingId.Hover;

constructor(
private readonly _editor: ICodeEditor,
@IKeybindingService private readonly _keybindingService: IKeybindingService
) {
this.options = {
language: this._editor.getModel()?.getLanguageId() ?? 'typescript',
type: AccessibleViewType.View
}
}

private _descriptionForCommand(commandId: string, msg: string, noKbMsg: string): string {
const kb = this._keybindingService.lookupKeybinding(commandId);
if (kb) {
return format(msg, kb.getAriaLabel());
}
return format(noKbMsg, commandId);
}

provideContent(): string {
const content: string[] = [];
content.push(HoverAccessibilityHelpNLS.intro);
const hoverController = HoverController.get(this._editor);
if (!hoverController) {
return content.join('\n');
}
const isFocusOnExpandableMarkdownHover = hoverController.isFocusOnMarkdownHoverWhichSupportsVerbosityAction(HoverVerbosityAction.Increase);
if (isFocusOnExpandableMarkdownHover) {
content.push(this._descriptionForCommand(INCREASE_HOVER_VERBOSITY_ACTION_ID, HoverAccessibilityHelpNLS.increaseVerbosity, HoverAccessibilityHelpNLS.increaseVerbosityNoKb));
}
const isFocusOnContractableMarkdownHover = hoverController.isFocusOnMarkdownHoverWhichSupportsVerbosityAction(HoverVerbosityAction.Decrease);
if (isFocusOnContractableMarkdownHover) {
content.push(this._descriptionForCommand(DECREASE_HOVER_VERBOSITY_ACTION_ID, HoverAccessibilityHelpNLS.decreaseVerbosity, HoverAccessibilityHelpNLS.decreaseVerbosityNoKb));
}
return content.join('\n');
}

onClose(): void {
HoverController.get(this._editor)?.focus();
}
}

export class ExtHoverAccessibleView implements IAccessibleViewImplentation {

readonly type = AccessibleViewType.View;
readonly priority = 90;
readonly name = 'extension-hover';
getProvider(accessor: ServicesAccessor) {

getProvider(accessor: ServicesAccessor): AdvancedContentProvider | undefined {
const contextViewService = accessor.get(IContextViewService);
const contextViewElement = contextViewService.getContextViewElement();
const extensionHoverContent = contextViewElement?.textContent ?? undefined;
Expand Down
4 changes: 4 additions & 0 deletions src/vs/editor/contrib/hover/browser/hoverController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,10 @@ export class HoverController extends Disposable implements IEditorContribution {
this._getOrCreateContentWidget().updateFocusedMarkdownHoverVerbosityLevel(action);
}

public isFocusOnMarkdownHoverWhichSupportsVerbosityAction(action: HoverVerbosityAction): boolean {
return this._getOrCreateContentWidget().isFocusOnMarkdownHoverWhichSupportsVerbosityAction(action);
}

public focus(): void {
this._contentWidget?.focus();
}
Expand Down
13 changes: 13 additions & 0 deletions src/vs/editor/contrib/hover/browser/markdownHoverParticipant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ export class MarkdownHoverParticipant implements IEditorHoverParticipant<Markdow
public updateFocusedMarkdownHoverPartVerbosityLevel(action: HoverVerbosityAction) {
this._renderedHoverParts?.updateFocusedHoverPartVerbosityLevel(action);
}

public isFocusOnMarkdownHoverWhichSupportsVerbosityAction(action: HoverVerbosityAction): boolean {
return this._renderedHoverParts?.isFocusOnMarkdownHoverWhichSupportsVerbosityAction(action) ?? false;
}
}

interface RenderedHoverPart {
Expand Down Expand Up @@ -378,6 +382,15 @@ class MarkdownRenderedHoverParts extends Disposable {
this._onFinishedRendering();
}

public isFocusOnMarkdownHoverWhichSupportsVerbosityAction(action: HoverVerbosityAction): boolean {
const hoverFocusedPartIndex = this._hoverFocusInfo.hoverPartIndex;
const hoverRenderedPart = this._getRenderedHoverPartAtIndex(hoverFocusedPartIndex);
if (!hoverRenderedPart || !hoverRenderedPart.hoverSource?.supportsVerbosityAction(action)) {
return false;
}
return true;
}

private _replaceRenderedHoverPartAtIndex(index: number, renderedHoverPart: RenderedHoverPart): void {
if (index >= this._renderHoverParts.length || index < 0) {
return;
Expand Down
Loading