mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
202 lines
8.3 KiB
TypeScript
202 lines
8.3 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
'use strict';
|
|
|
|
import EditorCommon = require('vs/editor/common/editorCommon');
|
|
import keyboardController = require('vs/base/browser/keyboardController');
|
|
import DomUtils = require('vs/base/browser/dom');
|
|
import Platform = require('vs/base/common/platform');
|
|
import Browser = require('vs/base/browser/browser');
|
|
import EditorBrowser = require('vs/editor/browser/editorBrowser');
|
|
import EventEmitter = require('vs/base/common/eventEmitter');
|
|
import {ViewEventHandler} from 'vs/editor/common/viewModel/viewEventHandler';
|
|
import Schedulers = require('vs/base/common/async');
|
|
import * as Lifecycle from 'vs/base/common/lifecycle';
|
|
import Strings = require('vs/base/common/strings');
|
|
import {Range} from 'vs/editor/common/core/range';
|
|
import {Position} from 'vs/editor/common/core/position';
|
|
import {CommonKeybindings} from 'vs/base/common/keyCodes';
|
|
import Event, {Emitter} from 'vs/base/common/event';
|
|
import {TextAreaHandler} from 'vs/editor/browser/controller/textAreaHandler';
|
|
import {ITextAreaWrapper, ITextAreaStyle, ISimpleModel} from 'vs/editor/browser/controller/textAreaState';
|
|
|
|
class TextAreaWrapper extends Lifecycle.Disposable implements ITextAreaWrapper {
|
|
|
|
private _textArea: HTMLTextAreaElement;
|
|
|
|
private _onKeyDown = this._register(new Emitter<DomUtils.IKeyboardEvent>());
|
|
public onKeyDown: Event<DomUtils.IKeyboardEvent> = this._onKeyDown.event;
|
|
|
|
private _onKeyUp = this._register(new Emitter<DomUtils.IKeyboardEvent>());
|
|
public onKeyUp: Event<DomUtils.IKeyboardEvent> = this._onKeyUp.event;
|
|
|
|
private _onKeyPress = this._register(new Emitter<DomUtils.IKeyboardEvent>());
|
|
public onKeyPress: Event<DomUtils.IKeyboardEvent> = this._onKeyPress.event;
|
|
|
|
private _onCompositionStart = this._register(new Emitter<void>());
|
|
public onCompositionStart: Event<void> = this._onCompositionStart.event;
|
|
|
|
private _onCompositionEnd = this._register(new Emitter<void>());
|
|
public onCompositionEnd: Event<void> = this._onCompositionEnd.event;
|
|
|
|
private _onInput = this._register(new Emitter<void>());
|
|
public onInput: Event<void> = this._onInput.event;
|
|
|
|
private _onCut = this._register(new Emitter<ClipboardEvent>());
|
|
public onCut: Event<ClipboardEvent> = this._onCut.event;
|
|
|
|
private _onCopy = this._register(new Emitter<ClipboardEvent>());
|
|
public onCopy: Event<ClipboardEvent> = this._onCopy.event;
|
|
|
|
private _onPaste = this._register(new Emitter<ClipboardEvent>());
|
|
public onPaste: Event<ClipboardEvent> = this._onPaste.event;
|
|
|
|
constructor(textArea: HTMLTextAreaElement) {
|
|
super();
|
|
this._textArea = textArea;
|
|
|
|
let kbController = this._register(new keyboardController.KeyboardController(this._textArea));
|
|
this._register(kbController.addListener2('keydown', (e) => this._onKeyDown.fire(e)));
|
|
this._register(kbController.addListener2('keyup', (e) => this._onKeyUp.fire(e)));
|
|
this._register(kbController.addListener2('keypress', (e) => this._onKeyPress.fire(e)));
|
|
|
|
this._register(DomUtils.addDisposableListener(this._textArea, 'compositionstart', (e) => this._onCompositionStart.fire()));
|
|
this._register(DomUtils.addDisposableListener(this._textArea, 'compositionend', (e) => this._onCompositionEnd.fire()));
|
|
this._register(DomUtils.addDisposableListener(this._textArea, 'input', (e) => this._onInput.fire()));
|
|
this._register(DomUtils.addDisposableListener(this._textArea, 'cut', (e) => this._onCut.fire(e)));
|
|
this._register(DomUtils.addDisposableListener(this._textArea, 'copy', (e) => this._onCopy.fire(e)));
|
|
this._register(DomUtils.addDisposableListener(this._textArea, 'paste', (e) => this._onPaste.fire(e)));
|
|
}
|
|
|
|
public get value(): string {
|
|
return this._textArea.value;
|
|
}
|
|
|
|
public set value(value:string) {
|
|
this._textArea.value = value;
|
|
}
|
|
|
|
public get selectionStart(): number {
|
|
return this._textArea.selectionStart;
|
|
}
|
|
|
|
public get selectionEnd(): number {
|
|
return this._textArea.selectionEnd;
|
|
}
|
|
|
|
public setSelectionRange(selectionStart:number, selectionEnd:number): void {
|
|
// console.log('setSelectionRange: ' + selectionStart + ', ' + selectionEnd);
|
|
try {
|
|
var scrollState = DomUtils.saveParentsScrollTop(this._textArea);
|
|
this._textArea.focus();
|
|
this._textArea.setSelectionRange(selectionStart, selectionEnd);
|
|
DomUtils.restoreParentsScrollTop(this._textArea, scrollState);
|
|
} catch(e) {
|
|
// Sometimes IE throws when setting selection (e.g. textarea is off-DOM)
|
|
console.log('an error has been thrown!');
|
|
}
|
|
}
|
|
|
|
public setStyle(style:ITextAreaStyle): void {
|
|
if (typeof style.top !== 'undefined') {
|
|
this._textArea.style.top = style.top;
|
|
}
|
|
if (typeof style.left !== 'undefined') {
|
|
this._textArea.style.left = style.left;
|
|
}
|
|
if (typeof style.width !== 'undefined') {
|
|
this._textArea.style.width = style.width;
|
|
}
|
|
if (typeof style.height !== 'undefined') {
|
|
this._textArea.style.height = style.height;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
export class KeyboardHandler extends ViewEventHandler implements Lifecycle.IDisposable {
|
|
|
|
private context:EditorBrowser.IViewContext;
|
|
private viewController:EditorBrowser.IViewController;
|
|
private viewHelper:EditorBrowser.IKeyboardHandlerHelper;
|
|
private textArea:TextAreaWrapper;
|
|
private textAreaHandler:TextAreaHandler;
|
|
|
|
constructor(context:EditorBrowser.IViewContext, viewController:EditorBrowser.IViewController, viewHelper:EditorBrowser.IKeyboardHandlerHelper) {
|
|
super();
|
|
|
|
this.context = context;
|
|
this.viewController = viewController;
|
|
this.textArea = new TextAreaWrapper(viewHelper.textArea);
|
|
this.viewHelper = viewHelper;
|
|
|
|
this.textAreaHandler = new TextAreaHandler(this.textArea, {
|
|
getModel: (): ISimpleModel => this.context.model,
|
|
emitKeyDown: (e:DomUtils.IKeyboardEvent): void => this.viewController.emitKeyDown(e),
|
|
emitKeyUp: (e:DomUtils.IKeyboardEvent): void => this.viewController.emitKeyUp(e),
|
|
paste: (source:string, txt:string, pasteOnNewLine:boolean): void => this.viewController.paste(source, txt, pasteOnNewLine),
|
|
type: (source:string, txt:string): void => this.viewController.type(source, txt),
|
|
replacePreviousChar: (source:string, txt:string): void => this.viewController.replacePreviousChar(source, txt),
|
|
cut: (source:string): void => this.viewController.cut(source),
|
|
visibleRangeForPositionRelativeToEditor: (lineNumber:number, column1:number, column2:number): { column1: EditorBrowser.VisibleRange; column2: EditorBrowser.VisibleRange; } => {
|
|
var revealInterestingColumn1Event:EditorCommon.IViewRevealRangeEvent = {
|
|
range: new Range(lineNumber, column1, lineNumber, column1),
|
|
verticalType: EditorCommon.VerticalRevealType.Simple,
|
|
revealHorizontal: true
|
|
};
|
|
this.context.privateViewEventBus.emit(EditorCommon.ViewEventNames.RevealRangeEvent, revealInterestingColumn1Event);
|
|
|
|
// Find range pixel position
|
|
var visibleRange1 = this.viewHelper.visibleRangeForPositionRelativeToEditor(lineNumber, column1);
|
|
var visibleRange2 = this.viewHelper.visibleRangeForPositionRelativeToEditor(lineNumber, column2);
|
|
|
|
return {
|
|
column1: visibleRange1,
|
|
column2: visibleRange2
|
|
}
|
|
},
|
|
startIME: (): void => {
|
|
DomUtils.addClass(this.viewHelper.viewDomNode, 'ime-input');
|
|
},
|
|
stopIME: (): void => {
|
|
DomUtils.removeClass(this.viewHelper.viewDomNode, 'ime-input');
|
|
}
|
|
}, this.context.configuration);
|
|
|
|
this.context.addEventHandler(this);
|
|
}
|
|
|
|
public dispose(): void {
|
|
this.context.removeEventHandler(this);
|
|
this.textAreaHandler.dispose();
|
|
this.textArea.dispose();
|
|
}
|
|
|
|
public onScrollChanged(e:EditorCommon.IScrollEvent): boolean {
|
|
this.textAreaHandler.onScrollChanged(e);
|
|
return false;
|
|
}
|
|
|
|
public onViewFocusChanged(isFocused:boolean): boolean {
|
|
this.textAreaHandler.onViewFocusChanged(isFocused);
|
|
return false;
|
|
}
|
|
|
|
public onCursorSelectionChanged(e:EditorCommon.IViewCursorSelectionChangedEvent): boolean {
|
|
this.textAreaHandler.onCursorSelectionChanged(e);
|
|
return false;
|
|
}
|
|
|
|
public onCursorPositionChanged(e:EditorCommon.IViewCursorPositionChangedEvent): boolean {
|
|
this.textAreaHandler.onCursorPositionChanged(e);
|
|
return false;
|
|
}
|
|
|
|
public onLayoutChanged(layoutInfo:EditorCommon.IEditorLayoutInfo): boolean {
|
|
this.textAreaHandler.onLayoutChanged(layoutInfo);
|
|
return false;
|
|
}
|
|
|
|
} |