Skip to content

Commit cc6ee0e

Browse files
committed
put cell output content into a11y view
1 parent 94db5c4 commit cc6ee0e

File tree

15 files changed

+93
-26
lines changed

15 files changed

+93
-26
lines changed

src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/contributedStatusBarItemController.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export class ContributedStatusBarItemController extends Disposable implements IN
4747
added: ICellViewModel[];
4848
removed: { handle: number }[];
4949
}): void {
50-
const vm = this._notebookEditor._getViewModel();
50+
const vm = this._notebookEditor.getViewModel();
5151
if (!vm) {
5252
return;
5353
}

src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/executionStatusBarItemController.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export class NotebookStatusBarController extends Disposable {
5858
}
5959

6060
private _updateVisibleCells(e: ICellVisibilityChangeEvent): void {
61-
const vm = this._notebookEditor._getViewModel();
61+
const vm = this._notebookEditor.getViewModel();
6262
if (!vm) {
6363
return;
6464
}

src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export class FindModel extends Disposable {
125125

126126
// we only update cell state if users are using the hybrid mode (both input and preview are enabled)
127127
const updateEditingState = () => {
128-
const viewModel = this._notebookEditor._getViewModel() as NotebookViewModel | undefined;
128+
const viewModel = this._notebookEditor.getViewModel() as NotebookViewModel | undefined;
129129
if (!viewModel) {
130130
return;
131131
}
@@ -164,7 +164,7 @@ export class FindModel extends Disposable {
164164

165165
if (e.isReplaceRevealed && !this._state.isReplaceRevealed) {
166166
// replace is hidden, we need to switch all markdown cells to preview mode
167-
const viewModel = this._notebookEditor._getViewModel() as NotebookViewModel | undefined;
167+
const viewModel = this._notebookEditor.getViewModel() as NotebookViewModel | undefined;
168168
if (!viewModel) {
169169
return;
170170
}

src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ class NotebookFindWidget extends SimpleFindReplaceWidget implements INotebookEdi
187187
const replacePattern = this.replacePattern;
188188
const replaceString = replacePattern.buildReplaceString(match.matches, this._state.preserveCase);
189189

190-
const viewModel = this._notebookEditor._getViewModel();
190+
const viewModel = this._notebookEditor.getViewModel();
191191
viewModel.replaceOne(cell, match.range, replaceString).then(() => {
192192
this._progressBar.stop();
193193
});
@@ -215,7 +215,7 @@ class NotebookFindWidget extends SimpleFindReplaceWidget implements INotebookEdi
215215
});
216216
});
217217

218-
const viewModel = this._notebookEditor._getViewModel();
218+
const viewModel = this._notebookEditor.getViewModel();
219219
viewModel.replaceAll(this._findModel.findMatches, replaceStrings).then(() => {
220220
this._progressBar.stop();
221221
});

src/vs/workbench/contrib/notebook/browser/contrib/navigation/arrow.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ registerAction2(class extends NotebookCellAction {
431431

432432
function getPageSize(context: INotebookCellActionContext) {
433433
const editor = context.notebookEditor;
434-
const layoutInfo = editor._getViewModel().layoutInfo;
434+
const layoutInfo = editor.getViewModel().layoutInfo;
435435
const lineHeight = layoutInfo?.fontInfo.lineHeight || 17;
436436
return Math.max(1, Math.floor((layoutInfo?.height || 0) / lineHeight) - 2);
437437
}

src/vs/workbench/contrib/notebook/browser/contrib/troubleshoot/layout.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export class TroubleshootController extends Disposable implements INotebookEdito
8282
});
8383
}));
8484

85-
const vm = this._notebookEditor._getViewModel();
85+
const vm = this._notebookEditor.getViewModel();
8686
let items: INotebookDeltaCellStatusBarItems[] = [];
8787

8888
if (this._enabled) {

src/vs/workbench/contrib/notebook/browser/contrib/undoRedo/notebookUndoRedo.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class NotebookUndoRedoContribution extends Disposable {
2121
const PRIORITY = 105;
2222
this._register(UndoCommand.addImplementation(PRIORITY, 'notebook-undo-redo', () => {
2323
const editor = getNotebookEditorFromEditorPane(this._editorService.activeEditorPane);
24-
const viewModel = editor?._getViewModel() as NotebookViewModel | undefined;
24+
const viewModel = editor?.getViewModel() as NotebookViewModel | undefined;
2525
if (editor && editor.hasModel() && viewModel) {
2626
return viewModel.undo().then(cellResources => {
2727
if (cellResources?.length) {
@@ -42,7 +42,7 @@ class NotebookUndoRedoContribution extends Disposable {
4242

4343
this._register(RedoCommand.addImplementation(PRIORITY, 'notebook-undo-redo', () => {
4444
const editor = getNotebookEditorFromEditorPane(this._editorService.activeEditorPane);
45-
const viewModel = editor?._getViewModel() as NotebookViewModel | undefined;
45+
const viewModel = editor?.getViewModel() as NotebookViewModel | undefined;
4646

4747
if (editor && editor.hasModel() && viewModel) {
4848
return viewModel.redo().then(cellResources => {

src/vs/workbench/contrib/notebook/browser/controller/cellOperations.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ export async function joinNotebookCells(editor: IActiveNotebookEditor, range: IC
498498
export async function joinCellsWithSurrounds(bulkEditService: IBulkEditService, context: INotebookCellActionContext, direction: 'above' | 'below'): Promise<void> {
499499
const editor = context.notebookEditor;
500500
const textModel = editor.textModel;
501-
const viewModel = editor._getViewModel() as NotebookViewModel;
501+
const viewModel = editor.getViewModel() as NotebookViewModel;
502502
let ret: {
503503
edits: ResourceEdit[];
504504
cell: ICellViewModel;
@@ -656,7 +656,7 @@ export function insertCell(
656656
initialText: string = '',
657657
ui: boolean = false
658658
) {
659-
const viewModel = editor._getViewModel() as NotebookViewModel;
659+
const viewModel = editor.getViewModel() as NotebookViewModel;
660660
const activeKernel = editor.activeKernel;
661661
if (viewModel.options.isReadOnly) {
662662
return null;

src/vs/workbench/contrib/notebook/browser/controller/foldingController.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class FoldingController extends Disposable implements INotebookEditorCont
4949

5050
this._foldingModel = new FoldingModel();
5151
this._localStore.add(this._foldingModel);
52-
this._foldingModel.attachViewModel(this._notebookEditor._getViewModel());
52+
this._foldingModel.attachViewModel(this._notebookEditor.getViewModel());
5353

5454
this._localStore.add(this._foldingModel.onDidFoldingRegionChanged(() => {
5555
this._updateEditorFoldingRanges();
@@ -103,7 +103,7 @@ export class FoldingController extends Disposable implements INotebookEditorCont
103103
return;
104104
}
105105

106-
const vm = this._notebookEditor._getViewModel() as NotebookViewModel;
106+
const vm = this._notebookEditor.getViewModel() as NotebookViewModel;
107107

108108
vm.updateFoldingRanges(this._foldingModel.regions);
109109
const hiddenRanges = vm.getHiddenRanges();
@@ -119,7 +119,7 @@ export class FoldingController extends Disposable implements INotebookEditorCont
119119
return;
120120
}
121121

122-
const viewModel = this._notebookEditor._getViewModel() as NotebookViewModel;
122+
const viewModel = this._notebookEditor.getViewModel() as NotebookViewModel;
123123
const target = e.event.target as HTMLElement;
124124

125125
if (target.classList.contains('codicon-notebook-collapsed') || target.classList.contains('codicon-notebook-expanded')) {
@@ -243,7 +243,7 @@ registerAction2(class extends Action2 {
243243
controller.setFoldingStateDown(index, CellFoldingState.Collapsed, levels);
244244
}
245245

246-
const viewIndex = editor._getViewModel().getNearestVisibleCellIndexUpwards(index);
246+
const viewIndex = editor.getViewModel().getNearestVisibleCellIndexUpwards(index);
247247
editor.focusElement(editor.cellAt(viewIndex));
248248
}
249249
}

src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import { ILabelService } from 'vs/platform/label/common/label';
5757
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
5858
import { NotebookRendererMessagingService } from 'vs/workbench/contrib/notebook/browser/services/notebookRendererMessagingServiceImpl';
5959
import { INotebookRendererMessagingService } from 'vs/workbench/contrib/notebook/common/notebookRendererMessagingService';
60+
import { getNotebookEditorFromEditorPane } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
6061

6162
// Editor Controller
6263
import 'vs/workbench/contrib/notebook/browser/controller/coreActions';
@@ -112,9 +113,10 @@ import { NotebookKernelHistoryService } from 'vs/workbench/contrib/notebook/brow
112113
import { INotebookLoggingService } from 'vs/workbench/contrib/notebook/common/notebookLoggingService';
113114
import { NotebookLoggingService } from 'vs/workbench/contrib/notebook/browser/services/notebookLoggingServiceImpl';
114115
import product from 'vs/platform/product/common/product';
115-
import { AccessibilityHelpAction } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution';
116-
import { NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
116+
import { AccessibilityHelpAction, AccessibleViewAction } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution';
117+
import { NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
117118
import { runAccessibilityHelpAction } from 'vs/workbench/contrib/notebook/browser/notebookAccessibilityHelp';
119+
import { AccessibleViewType, IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView';
118120

119121
/*--------------------------------------------------------------------------------------------- */
120122

@@ -689,6 +691,70 @@ class NotebookAccessibilityHelpContribution extends Disposable {
689691
}
690692
}
691693

694+
class NotebookAccessibleViewContribution extends Disposable {
695+
static ID: 'chatAccessibleViewContribution';
696+
constructor() {
697+
super();
698+
this._register(AccessibleViewAction.addImplementation(100, 'notebook', accessor => {
699+
const accessibleViewService = accessor.get(IAccessibleViewService);
700+
701+
const activePane = accessor.get(IEditorService).activeEditorPane;
702+
const notebookEditor = getNotebookEditorFromEditorPane(activePane);
703+
const notebookViewModel = notebookEditor?.getViewModel();
704+
const selections = notebookViewModel?.getSelections();
705+
notebookViewModel?.getCellIndex;
706+
const notebookDocument = notebookViewModel?.notebookDocument;
707+
708+
if (!selections || !notebookDocument || !notebookEditor?.textModel) {
709+
return false;
710+
}
711+
712+
const viewCell = notebookViewModel.viewCells[selections[0].start];
713+
let outputContent = '';
714+
const decoder = new TextDecoder();
715+
for (let i = 0; i < viewCell.outputsViewModels.length; i++) {
716+
const outputViewModel = viewCell.outputsViewModels[i];
717+
const outputTextModel = viewCell.model.outputs[i];
718+
const [mimeTypes, pick] = outputViewModel.resolveMimeTypes(notebookEditor.textModel, undefined);
719+
const mimeType = mimeTypes[pick].mimeType;
720+
const pickedBuffer = outputTextModel.outputs.find(output => output.mime === mimeType)?.data.buffer;
721+
722+
let text = `${mimeType}\n`;
723+
if (!pickedBuffer || mimeType.startsWith('image')) {
724+
const altBuffer = outputTextModel.outputs.find(output => !output.mime.startsWith('image'))?.data.buffer;
725+
if (altBuffer) {
726+
text = decoder.decode(altBuffer);
727+
}
728+
} else {
729+
text = decoder.decode(pickedBuffer);
730+
}
731+
732+
outputContent = outputContent.concat(`${text}\n`);
733+
}
734+
735+
if (!outputContent) {
736+
return false;
737+
}
738+
739+
accessibleViewService.show({
740+
verbositySettingKey: 'notebook',
741+
provideContent(): string { return outputContent; },
742+
onClose() {
743+
notebookEditor?.setFocus(selections[0]);
744+
activePane?.focus();
745+
},
746+
options: {
747+
ariaLabel: nls.localize('NotebookCellOutputAccessibleView', "Notebook Cell Output Accessible View"),
748+
language: 'plaintext',
749+
type: AccessibleViewType.View
750+
}
751+
});
752+
return true;
753+
}, NOTEBOOK_OUTPUT_FOCUSED));
754+
}
755+
}
756+
757+
692758
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
693759
workbenchContributionsRegistry.registerWorkbenchContribution(NotebookContribution, LifecyclePhase.Starting);
694760
workbenchContributionsRegistry.registerWorkbenchContribution(CellContentProvider, LifecyclePhase.Starting);
@@ -698,6 +764,7 @@ workbenchContributionsRegistry.registerWorkbenchContribution(NotebookEditorManag
698764
workbenchContributionsRegistry.registerWorkbenchContribution(NotebookLanguageSelectorScoreRefine, LifecyclePhase.Ready);
699765
workbenchContributionsRegistry.registerWorkbenchContribution(SimpleNotebookWorkingCopyEditorHandler, LifecyclePhase.Ready);
700766
workbenchContributionsRegistry.registerWorkbenchContribution(NotebookAccessibilityHelpContribution, LifecyclePhase.Eventually);
767+
workbenchContributionsRegistry.registerWorkbenchContribution(NotebookAccessibleViewContribution, LifecyclePhase.Eventually);
701768

702769
registerSingleton(INotebookService, NotebookService, InstantiationType.Delayed);
703770
registerSingleton(INotebookEditorWorkerService, NotebookEditorWorkerServiceImpl, InstantiationType.Delayed);

0 commit comments

Comments
 (0)