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

Explore Adopting EditContext API #207699

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,10 @@
"presentation": {
"group": "0_vscode",
"order": 3
}
},
"vscode-diagnostic-tools.debuggerScripts": [
"${workspaceFolder}/scripts/hot-reload-injected-script.js"
]
},
{
"type": "node",
Expand Down
1 change: 1 addition & 0 deletions src/vs/base/common/hotReload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import { env } from 'vs/base/common/process';

export function isHotReloadEnabled(): boolean {
return true;
return env && !!env['VSCODE_DEV'];

Check failure on line 11 in src/vs/base/common/hotReload.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

Unreachable code detected.

Check failure on line 11 in src/vs/base/common/hotReload.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

Unreachable code detected.

Check failure on line 11 in src/vs/base/common/hotReload.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

Unreachable code detected.

Check failure on line 11 in src/vs/base/common/hotReload.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

Unreachable code detected.
}
export function registerHotReloadHandler(handler: HotReloadHandler): IDisposable {
if (!isHotReloadEnabled()) {
Expand Down
17 changes: 17 additions & 0 deletions src/vs/editor/browser/controller/editContext/editContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { FastDomNode } from 'vs/base/browser/fastDomNode';
import { IEditorAriaOptions } from 'vs/editor/browser/editorBrowser';
import { ViewPart } from 'vs/editor/browser/view/viewPart';

export abstract class AbstractEditContext extends ViewPart {
abstract isFocused(): boolean;
abstract appendTo(overflowGuardContainer: FastDomNode<HTMLElement>): void;
abstract writeScreenReaderContent(reason: string): void;
abstract focusTextArea(): void;
abstract refreshFocusState(): void;
abstract setAriaOptions(options: IEditorAriaOptions): void;
}
9 changes: 9 additions & 0 deletions src/vs/editor/browser/controller/editContext/impl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { NativeEditContext } from 'vs/editor/browser/controller/editContext/native/nativeEditContext';
import { TextAreaHandler } from 'vs/editor/browser/controller/editContext/textArea/textAreaHandler';

export const EditContextImpl = false ? TextAreaHandler : NativeEditContext;
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

export class DebugEditContext extends EditContext {

Check failure on line 6 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

Cannot find name 'EditContext'.

Check failure on line 6 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

Cannot find name 'EditContext'.

Check failure on line 6 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

Cannot find name 'EditContext'.

Check failure on line 6 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

Cannot find name 'EditContext'.
private _isDebugging = true;
private _controlBounds: DOMRect | null = null;
private _selectionBounds: DOMRect | null = null;
private _characterBounds: { rangeStart: number; characterBounds: DOMRect[] } | null = null;

constructor(options?: EditContextInit | undefined) {

Check failure on line 12 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

Cannot find name 'EditContextInit'.

Check failure on line 12 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

Cannot find name 'EditContextInit'.

Check failure on line 12 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

Cannot find name 'EditContextInit'.

Check failure on line 12 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

Cannot find name 'EditContextInit'.
super(options);
}

override updateText(rangeStart: number, rangeEnd: number, text: string): void {

Check failure on line 16 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 16 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 16 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 16 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.
super.updateText(rangeStart, rangeEnd, text);
this.renderDebug();
}
override updateSelection(start: number, end: number): void {

Check failure on line 20 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 20 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 20 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 20 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.
super.updateSelection(start, end);
this.renderDebug();
}
override updateControlBounds(controlBounds: DOMRect): void {

Check failure on line 24 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 24 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 24 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 24 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.
super.updateControlBounds(controlBounds);
this._controlBounds = controlBounds;
this.renderDebug();
}
override updateSelectionBounds(selectionBounds: DOMRect): void {

Check failure on line 29 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 29 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 29 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 29 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.
super.updateSelectionBounds(selectionBounds);
this._selectionBounds = selectionBounds;
this.renderDebug();
}
override updateCharacterBounds(rangeStart: number, characterBounds: DOMRect[]): void {

Check failure on line 34 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 34 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 34 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 34 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.
super.updateCharacterBounds(rangeStart, characterBounds);
this._characterBounds = { rangeStart, characterBounds };
this.renderDebug();
}
override attachedElements(): HTMLElement[] {

Check failure on line 39 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 39 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 39 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 39 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.
return super.attachedElements();
}

override characterBounds(): DOMRect[] {

Check failure on line 43 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 43 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 43 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.

Check failure on line 43 in src/vs/editor/browser/controller/editContext/native/debugEditContext.ts

View workflow job for this annotation

GitHub Actions / Monaco Editor checks

This member cannot have an 'override' modifier because its containing class 'DebugEditContext' does not extend another class.
return super.characterBounds();
}

private readonly _ontextupdateWrapper = new EventListenerWrapper('textupdate', this);
private readonly _ontextformatupdateWrapper = new EventListenerWrapper('textformatupdate', this);
private readonly _oncharacterboundsupdateWrapper = new EventListenerWrapper('characterboundsupdate', this);
private readonly _oncompositionstartWrapper = new EventListenerWrapper('compositionstart', this);
private readonly _oncompositionendWrapper = new EventListenerWrapper('compositionend', this);

override get ontextupdate(): EventHandler | null { return this._ontextupdateWrapper.eventHandler; }
override set ontextupdate(value: EventHandler | null) { this._ontextupdateWrapper.eventHandler = value; }
override get ontextformatupdate(): EventHandler | null { return this._ontextformatupdateWrapper.eventHandler; }
override set ontextformatupdate(value: EventHandler | null) { this._ontextformatupdateWrapper.eventHandler = value; }
override get oncharacterboundsupdate(): EventHandler | null { return this._oncharacterboundsupdateWrapper.eventHandler; }
override set oncharacterboundsupdate(value: EventHandler | null) { this._oncharacterboundsupdateWrapper.eventHandler = value; }
override get oncompositionstart(): EventHandler | null { return this._oncompositionstartWrapper.eventHandler; }
override set oncompositionstart(value: EventHandler | null) { this._oncompositionstartWrapper.eventHandler = value; }
override get oncompositionend(): EventHandler | null { return this._oncompositionendWrapper.eventHandler; }
override set oncompositionend(value: EventHandler | null) { this._oncompositionendWrapper.eventHandler = value; }


private readonly _listenerMap = new Map<EventListenerOrEventListenerObject, EventListenerOrEventListenerObject>();

override addEventListener<K extends keyof EditContextEventHandlersEventMap>(type: K, listener: (this: GlobalEventHandlers, ev: EditContextEventHandlersEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
override addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void {
if (!listener) { return; }

const debugListener = (event: Event) => {
if (this._isDebugging) {
this.renderDebug();
console.log(`DebugEditContex.on_${type}`, event);
}

if (typeof listener === 'function') {
listener.call(this, event);
} else if (typeof listener === 'object' && 'handleEvent' in listener) {
listener.handleEvent(event);
}
};
this._listenerMap.set(listener, debugListener);
super.addEventListener(type, debugListener, options);

this.renderDebug();
}

override removeEventListener(type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | EventListenerOptions | undefined): void {
if (!listener) { return; }

const debugListener = this._listenerMap.get(listener);
if (debugListener) {
super.removeEventListener(type, debugListener, options);
this._listenerMap.delete(listener);
}

this.renderDebug();
}

override dispatchEvent(event: Event): boolean {
return super.dispatchEvent(event);
}

public startDebugging() {
this._isDebugging = true;
this.renderDebug();
}

public endDebugging() {
this._isDebugging = false;
this.renderDebug();
}

private _disposables: { dispose(): void }[] = [];

public renderDebug() {
this._disposables.forEach(d => d.dispose());
this._disposables = [];

if (!this._isDebugging || this._listenerMap.size === 0) {
return;
}

if (this._controlBounds) {
this._disposables.push(createRect(this._controlBounds));
}
if (this._selectionBounds) {
this._disposables.push(createRect(this._selectionBounds));
}
if (this._characterBounds) {
for (const rect of this._characterBounds.characterBounds) {
this._disposables.push(createRect(rect));
}
}

this._disposables.push(createDiv(this.text, this.selectionStart, this.selectionEnd));
}
}

function createDiv(text: string, selectionStart: number, selectionEnd: number) {
const ret = document.createElement('div');
ret.style.position = 'absolute';
ret.style.zIndex = '999999999';
ret.style.bottom = '50px';
ret.style.left = '60px';
ret.style.backgroundColor = 'white';
ret.style.border = '1px solid black';
ret.style.padding = '5px';
ret.style.whiteSpace = 'pre';
ret.className = 'debug-rect-marker';
ret.style.font = '12px monospace';
ret.style.pointerEvents = 'none';

const before = text.substring(0, selectionStart);
const selected = text.substring(selectionStart, selectionEnd) || '|';
const after = text.substring(selectionEnd) + ' ';

const beforeNode = document.createTextNode(before);
ret.appendChild(beforeNode);

const selectedNode = document.createElement('span');
selectedNode.style.backgroundColor = 'yellow';
selectedNode.appendChild(document.createTextNode(selected));

selectedNode.style.minWidth = '2px';
selectedNode.style.minHeight = '16px';
ret.appendChild(selectedNode);

const afterNode = document.createTextNode(after);
ret.appendChild(afterNode);


// eslint-disable-next-line no-restricted-syntax
document.body.appendChild(ret);

return {
dispose: () => {
ret.remove();
}
};
}

function createRect(rect: DOMRect) {
const ret = document.createElement('div');
ret.style.position = 'absolute';
ret.style.zIndex = '999999999';
ret.style.outline = '2px solid red';
ret.className = 'debug-rect-marker';
ret.style.pointerEvents = 'none';

ret.style.top = rect.top + 'px';
ret.style.left = rect.left + 'px';
ret.style.width = rect.width + 'px';
ret.style.height = rect.height + 'px';

// eslint-disable-next-line no-restricted-syntax
document.body.appendChild(ret);

return {
dispose: () => {
ret.remove();
}
};
}

class EventListenerWrapper {
private _eventHandler: EventHandler | null = null;

constructor(
private readonly _eventType: string,
private readonly _target: EventTarget,
) {
}

get eventHandler(): EventHandler | null {
return this._eventHandler;
}

set eventHandler(value: EventHandler | null) {
if (this._eventHandler) {
this._target.removeEventListener(this._eventType, this._eventHandler);
}
this._eventHandler = value;
if (value) {
this._target.addEventListener(this._eventType, value);
}
}
}


Loading
Loading