提交 c3ce6210 编写于 作者: A Alex Dima

Debt: Simplify TextAreaHandler

上级 9cdd0987
......@@ -7,8 +7,8 @@
import * as browser from 'vs/base/browser/browser';
import * as dom from 'vs/base/browser/dom';
import { GlobalScreenReaderNVDA } from 'vs/editor/common/config/commonEditorConfig';
import { TextAreaHandler } from 'vs/editor/browser/controller/textAreaHandler';
import { TextAreaStrategy } from 'vs/editor/browser/controller/textAreaState';
import { TextAreaHandler, ITextAreaHandlerHost } from 'vs/editor/browser/controller/textAreaHandler';
import { TextAreaStrategy, ISimpleModel } from 'vs/editor/browser/controller/textAreaState';
import { Range } from 'vs/editor/common/core/range';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
import { Configuration } from 'vs/editor/browser/config/configuration';
......@@ -18,6 +18,7 @@ import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { FastDomNode } from 'vs/base/browser/fastDomNode';
import { VerticalRevealType } from 'vs/editor/common/controller/cursorEvents';
import { ViewController } from 'vs/editor/browser/view/viewController';
import { EndOfLinePreference } from "vs/editor/common/editorCommon";
export interface IKeyboardHandlerHelper {
viewDomNode: FastDomNode<HTMLElement>;
......@@ -41,16 +42,20 @@ export class KeyboardHandler extends ViewEventHandler {
private _context: ViewContext;
private viewController: ViewController;
private viewHelper: IKeyboardHandlerHelper;
private textArea: FastDomNode<HTMLTextAreaElement>;
private textAreaHandler: TextAreaHandler;
private viewHelper: IKeyboardHandlerHelper;
private visiblePosition: TextAreaVisiblePosition;
private contentLeft: number;
private contentWidth: number;
private scrollLeft: number;
private scrollTop: number;
private visiblePosition: TextAreaVisiblePosition;
private _selections: Range[];
private _lastCopiedValue: string;
private _lastCopiedValueIsFromEmptySelection: boolean;
private textAreaHandler: TextAreaHandler;
constructor(context: ViewContext, viewController: ViewController, viewHelper: IKeyboardHandlerHelper) {
super();
......@@ -67,11 +72,55 @@ export class KeyboardHandler extends ViewEventHandler {
this.scrollLeft = 0;
this.scrollTop = 0;
this.textAreaHandler = new TextAreaHandler(this._getStrategy(), this.textArea, this._context.model);
this._selections = [new Range(1, 1, 1, 1)];
this._lastCopiedValue = null;
this._lastCopiedValueIsFromEmptySelection = false;
const textAreaHandlerHost: ITextAreaHandlerHost = {
getPlainTextToCopy: (): string => {
const whatToCopy = this._context.model.getPlainTextToCopy(this._selections, browser.enableEmptySelectionClipboard);
if (browser.enableEmptySelectionClipboard) {
if (browser.isFirefox) {
// When writing "LINE\r\n" to the clipboard and then pasting,
// Firefox pastes "LINE\n", so let's work around this quirk
this._lastCopiedValue = whatToCopy.replace(/\r\n/g, '\n');
} else {
this._lastCopiedValue = whatToCopy;
}
let selections = this._selections;
this._lastCopiedValueIsFromEmptySelection = (selections.length === 1 && selections[0].isEmpty());
}
return whatToCopy;
},
getHTMLToCopy: (): string => {
return this._context.model.getHTMLToCopy(this._selections, browser.enableEmptySelectionClipboard);
}
};
const simpleModel: ISimpleModel = {
getLineCount: (): number => {
return this._context.model.getLineCount();
},
getLineMaxColumn: (lineNumber: number): number => {
return this._context.model.getLineMaxColumn(lineNumber);
},
getValueInRange: (range: Range, eol: EndOfLinePreference): string => {
return this._context.model.getValueInRange(range, eol);
}
};
this.textAreaHandler = new TextAreaHandler(textAreaHandlerHost, this._getStrategy(), this.textArea, simpleModel);
this._register(this.textAreaHandler.onKeyDown((e) => this.viewController.emitKeyDown(e)));
this._register(this.textAreaHandler.onKeyUp((e) => this.viewController.emitKeyUp(e)));
this._register(this.textAreaHandler.onPaste((e) => this.viewController.paste('keyboard', e.text, e.pasteOnNewLine)));
this._register(this.textAreaHandler.onPaste((e) => {
let pasteOnNewLine = false;
if (browser.enableEmptySelectionClipboard) {
pasteOnNewLine = (e.text === this._lastCopiedValue && this._lastCopiedValueIsFromEmptySelection);
}
this.viewController.paste('keyboard', e.text, pasteOnNewLine);
}));
this._register(this.textAreaHandler.onCut((e) => this.viewController.cut('keyboard')));
this._register(this.textAreaHandler.onType((e) => {
if (e.replaceCharCnt) {
......@@ -80,9 +129,9 @@ export class KeyboardHandler extends ViewEventHandler {
this.viewController.type('keyboard', e.text);
}
}));
this._register(this.textAreaHandler.onCompositionStart((e) => {
const lineNumber = e.showAtLineNumber;
const column = e.showAtColumn;
this._register(this.textAreaHandler.onCompositionStart(() => {
const lineNumber = this._selections[0].startLineNumber;
const column = this._selections[0].startColumn;
this._context.privateViewEventBus.emit(new viewEvents.ViewRevealRangeRequestEvent(
new Range(lineNumber, column, lineNumber, column),
......@@ -132,7 +181,7 @@ export class KeyboardHandler extends ViewEventHandler {
}
}));
this._register(this.textAreaHandler.onCompositionEnd((e) => {
this._register(this.textAreaHandler.onCompositionEnd(() => {
this.textArea.unsetHeight();
this.textArea.unsetWidth();
this.textArea.setLeft(0);
......@@ -190,6 +239,7 @@ export class KeyboardHandler extends ViewEventHandler {
private _lastCursorSelectionChanged: viewEvents.ViewCursorSelectionChangedEvent = null;
public onCursorSelectionChanged(e: viewEvents.ViewCursorSelectionChangedEvent): boolean {
this._selections = [e.selection].concat(e.secondarySelections);
this._lastCursorSelectionChanged = e;
return false;
}
......
......@@ -32,12 +32,6 @@ const enum ReadFromTextArea {
export interface IPasteData {
text: string;
pasteOnNewLine: boolean;
}
export interface ICompositionStartData {
showAtLineNumber: number;
showAtColumn: number;
}
// See https://github.com/Microsoft/monaco-editor/issues/320
......@@ -47,6 +41,11 @@ const isChromev55_v56 = (
&& navigator.userAgent.indexOf('Edge/') === -1
);
export interface ITextAreaHandlerHost {
getPlainTextToCopy(): string;
getHTMLToCopy(): string;
}
export class TextAreaHandler extends Disposable {
private _onKeyDown = this._register(new Emitter<IKeyboardEvent>());
......@@ -64,72 +63,81 @@ export class TextAreaHandler extends Disposable {
private _onType = this._register(new Emitter<ITypeData>());
public onType: Event<ITypeData> = this._onType.event;
private _onCompositionStart = this._register(new Emitter<ICompositionStartData>());
public onCompositionStart: Event<ICompositionStartData> = this._onCompositionStart.event;
private _onCompositionStart = this._register(new Emitter<void>());
public onCompositionStart: Event<void> = this._onCompositionStart.event;
private _onCompositionUpdate = this._register(new Emitter<ICompositionEvent>());
public onCompositionUpdate: Event<ICompositionEvent> = this._onCompositionUpdate.event;
private _onCompositionEnd = this._register(new Emitter<ICompositionEvent>());
public onCompositionEnd: Event<ICompositionEvent> = this._onCompositionEnd.event;
private _onCompositionEnd = this._register(new Emitter<void>());
public onCompositionEnd: Event<void> = this._onCompositionEnd.event;
private textArea: TextAreaWrapper;
private model: ISimpleModel;
// ---
private selection: Range;
private selections: Range[];
private hasFocus: boolean;
private readonly _host: ITextAreaHandlerHost;
private readonly _textArea: TextAreaWrapper;
private readonly _model: ISimpleModel;
private asyncTriggerCut: RunOnceScheduler;
private _selection: Range;
private _hasFocus: boolean;
private textAreaState: TextAreaState;
private textareaIsShownAtCursor: boolean;
private readonly _asyncTriggerCut: RunOnceScheduler;
private lastCopiedValue: string;
private lastCopiedValueIsFromEmptySelection: boolean;
private _textAreaState: TextAreaState;
private _isDoingComposition: boolean;
private _nextCommand: ReadFromTextArea;
constructor(strategy: TextAreaStrategy, textArea: FastDomNode<HTMLTextAreaElement>, model: ISimpleModel) {
constructor(host: ITextAreaHandlerHost, strategy: TextAreaStrategy, textArea: FastDomNode<HTMLTextAreaElement>, model: ISimpleModel) {
super();
this.textArea = this._register(new TextAreaWrapper(textArea));
this.model = model;
this.selection = new Range(1, 1, 1, 1);
this.selections = [new Range(1, 1, 1, 1)];
this._nextCommand = ReadFromTextArea.Type;
this._host = host;
this._textArea = this._register(new TextAreaWrapper(textArea));
this._model = model;
this._selection = new Range(1, 1, 1, 1);
this._hasFocus = false;
this._asyncTriggerCut = this._register(new RunOnceScheduler(() => this._onCut.fire(), 0));
this._textAreaState = createTextAreaState(strategy);
this._isDoingComposition = false;
this.asyncTriggerCut = this._register(new RunOnceScheduler(() => this._onCut.fire(), 0));
this._nextCommand = ReadFromTextArea.Type;
this.lastCopiedValue = null;
this.lastCopiedValueIsFromEmptySelection = false;
this.textAreaState = createTextAreaState(strategy);
this._register(dom.addStandardDisposableListener(textArea.domNode, 'keydown', (e: IKeyboardEvent) => {
if (this._isDoingComposition && e.equals(KeyCode.KEY_IN_COMPOSITION)) {
// Stop propagation for keyDown events if the IME is processing key input
e.stopPropagation();
}
this.hasFocus = false;
if (e.equals(KeyCode.Escape)) {
// Prevent default always for `Esc`, otherwise it will generate a keypress
// See https://msdn.microsoft.com/en-us/library/ie/ms536939(v=vs.85).aspx
e.preventDefault();
}
this._onKeyDown.fire(e);
}));
this._register(dom.addStandardDisposableListener(textArea.domNode, 'keydown', (e: IKeyboardEvent) => this._onKeyDownHandler(e)));
this._register(dom.addStandardDisposableListener(textArea.domNode, 'keyup', (e: IKeyboardEvent) => this._onKeyUp.fire(e)));
this._register(dom.addStandardDisposableListener(textArea.domNode, 'keypress', (e: IKeyboardEvent) => this._onKeyPressHandler(e)));
this._register(dom.addStandardDisposableListener(textArea.domNode, 'keyup', (e: IKeyboardEvent) => {
this._onKeyUp.fire(e);
}));
this.textareaIsShownAtCursor = false;
let compositionLocale = null;
this._register(dom.addDisposableListener(textArea.domNode, 'compositionstart', (e: CompositionEvent) => {
if (this.textareaIsShownAtCursor) {
if (this._isDoingComposition) {
return;
}
this.textareaIsShownAtCursor = true;
this._isDoingComposition = true;
// In IE we cannot set .value when handling 'compositionstart' because the entire composition will get canceled.
if (!browser.isEdgeOrIE) {
this.setTextAreaState('compositionstart', this.textAreaState.toEmpty(), false);
this.setTextAreaState('compositionstart', this._textAreaState.toEmpty(), false);
}
this._onCompositionStart.fire({
showAtLineNumber: this.selection.startLineNumber,
showAtColumn: this.selection.startColumn
});
this._onCompositionStart.fire();
}));
this._register(dom.addDisposableListener(textArea.domNode, 'compositionupdate', (e: CompositionEvent) => {
......@@ -148,75 +156,55 @@ export class TextAreaHandler extends Disposable {
// Multi-part Japanese compositions reset cursor in Edge/IE, Chinese and Korean IME don't have this issue.
// The reason that we can't use this path for all CJK IME is IE and Edge behave differently when handling Korean IME,
// which breaks this path of code.
this.textAreaState = this.textAreaState.fromTextArea(this.textArea);
let typeInput = this.textAreaState.deduceInput();
this._textAreaState = this._textAreaState.fromTextArea(this._textArea);
let typeInput = this._textAreaState.deduceInput();
this._onType.fire(typeInput);
this._onCompositionUpdate.fire(e);
return;
}
this.textAreaState = this.textAreaState.fromText(e.data);
let typeInput = this.textAreaState.updateComposition();
this._textAreaState = this._textAreaState.fromText(e.data);
let typeInput = this._textAreaState.updateComposition();
this._onType.fire(typeInput);
this._onCompositionUpdate.fire(e);
}));
let readFromTextArea = () => {
let tempTextAreaState = this.textAreaState.fromTextArea(this.textArea);
let typeInput = tempTextAreaState.deduceInput();
if (typeInput.replaceCharCnt === 0 && typeInput.text.length === 1 && strings.isHighSurrogate(typeInput.text.charCodeAt(0))) {
// Ignore invalid input but keep it around for next time
return;
}
this.textAreaState = tempTextAreaState;
// console.log('==> DEDUCED INPUT: ' + JSON.stringify(typeInput));
if (this._nextCommand === ReadFromTextArea.Type) {
if (typeInput.text !== '') {
this._onType.fire(typeInput);
}
} else {
this.executePaste(typeInput.text);
this._nextCommand = ReadFromTextArea.Type;
}
};
this._register(dom.addDisposableListener(textArea.domNode, 'compositionend', (e: CompositionEvent) => {
// console.log('onCompositionEnd: ' + e.data);
if (browser.isEdgeOrIE && e.locale === 'ja') {
// https://github.com/Microsoft/monaco-editor/issues/339
this.textAreaState = this.textAreaState.fromTextArea(this.textArea);
let typeInput = this.textAreaState.deduceInput();
this._textAreaState = this._textAreaState.fromTextArea(this._textArea);
let typeInput = this._textAreaState.deduceInput();
this._onType.fire(typeInput);
}
else {
this.textAreaState = this.textAreaState.fromText(e.data);
let typeInput = this.textAreaState.updateComposition();
this._textAreaState = this._textAreaState.fromText(e.data);
let typeInput = this._textAreaState.updateComposition();
this._onType.fire(typeInput);
}
// Due to isEdgeOrIE (where the textarea was not cleared initially) and isChrome (the textarea is not updated correctly when composition ends)
// we cannot assume the text at the end consists only of the composited text
if (browser.isEdgeOrIE || browser.isChrome) {
this.textAreaState = this.textAreaState.fromTextArea(this.textArea);
this._textAreaState = this._textAreaState.fromTextArea(this._textArea);
}
if (!this.textareaIsShownAtCursor) {
if (!this._isDoingComposition) {
return;
}
this.textareaIsShownAtCursor = false;
this._isDoingComposition = false;
this._onCompositionEnd.fire();
}));
this._register(dom.addDisposableListener(textArea.domNode, 'input', () => {
// console.log('onInput: ' + this.textArea.getValue());
if (this.textareaIsShownAtCursor) {
if (this._isDoingComposition) {
// See https://github.com/Microsoft/monaco-editor/issues/320
if (isChromev55_v56) {
let text = this.textArea.getValue();
this.textAreaState = this.textAreaState.fromText(text);
let typeInput = this.textAreaState.updateComposition();
let text = this._textArea.getValue();
this._textAreaState = this._textAreaState.fromText(text);
let typeInput = this._textAreaState.updateComposition();
this._onType.fire(typeInput);
let e = {
locale: compositionLocale,
......@@ -228,14 +216,30 @@ export class TextAreaHandler extends Disposable {
return;
}
readFromTextArea();
let tempTextAreaState = this._textAreaState.fromTextArea(this._textArea);
let typeInput = tempTextAreaState.deduceInput();
if (typeInput.replaceCharCnt === 0 && typeInput.text.length === 1 && strings.isHighSurrogate(typeInput.text.charCodeAt(0))) {
// Ignore invalid input but keep it around for next time
return;
}
this._textAreaState = tempTextAreaState;
// console.log('==> DEDUCED INPUT: ' + JSON.stringify(typeInput));
if (this._nextCommand === ReadFromTextArea.Type) {
if (typeInput.text !== '') {
this._onType.fire(typeInput);
}
} else {
this.executePaste(typeInput.text);
this._nextCommand = ReadFromTextArea.Type;
}
}));
// --- Clipboard operations
this._register(dom.addDisposableListener(textArea.domNode, 'cut', (e: ClipboardEvent) => {
this._ensureClipboardGetsEditorSelection(e);
this.asyncTriggerCut.schedule();
this._asyncTriggerCut.schedule();
}));
this._register(dom.addDisposableListener(textArea.domNode, 'copy', (e: ClipboardEvent) => {
......@@ -246,9 +250,9 @@ export class TextAreaHandler extends Disposable {
if (ClipboardEventUtils.canUseTextData(e)) {
this.executePaste(ClipboardEventUtils.getTextData(e));
} else {
if (this.textArea.getSelectionStart() !== this.textArea.getSelectionEnd()) {
if (this._textArea.getSelectionStart() !== this._textArea.getSelectionEnd()) {
// Clean up the textarea, to get a clean paste
this.setTextAreaState('paste', this.textAreaState.toEmpty(), false);
this.setTextAreaState('paste', this._textAreaState.toEmpty(), false);
}
this._nextCommand = ReadFromTextArea.Paste;
}
......@@ -264,56 +268,34 @@ export class TextAreaHandler extends Disposable {
// --- begin event handlers
public setStrategy(strategy: TextAreaStrategy): void {
this.textAreaState = this.textAreaState.toStrategy(strategy);
this._textAreaState = this._textAreaState.toStrategy(strategy);
}
public setHasFocus(isFocused: boolean): void {
if (this.hasFocus === isFocused) {
if (this._hasFocus === isFocused) {
// no change
return;
}
this.hasFocus = isFocused;
if (this.hasFocus) {
this._hasFocus = isFocused;
if (this._hasFocus) {
this._writePlaceholderAndSelectTextArea('focusgain', false);
}
}
public setCursorSelections(primary: Range, secondary: Range[]): void {
this.selection = primary;
this.selections = [primary].concat(secondary);
this._selection = primary;
this._writePlaceholderAndSelectTextArea('selection changed', false);
}
// --- end event handlers
private setTextAreaState(reason: string, textAreaState: TextAreaState, forceFocus: boolean): void {
if (!this.hasFocus) {
if (!this._hasFocus) {
textAreaState = textAreaState.resetSelection();
}
textAreaState.applyToTextArea(reason, this.textArea, this.hasFocus || forceFocus);
this.textAreaState = textAreaState;
}
private _onKeyDownHandler(e: IKeyboardEvent): void {
if (this.textareaIsShownAtCursor && e.equals(KeyCode.KEY_IN_COMPOSITION)) {
// Stop propagation for keyDown events if the IME is processing key input
e.stopPropagation();
}
if (e.equals(KeyCode.Escape)) {
// Prevent default always for `Esc`, otherwise it will generate a keypress
// See https://msdn.microsoft.com/en-us/library/ie/ms536939(v=vs.85).aspx
e.preventDefault();
}
this._onKeyDown.fire(e);
}
private _onKeyPressHandler(e: IKeyboardEvent): void {
if (!this.hasFocus) {
// Sometimes, when doing Alt-Tab, in FF, a 'keypress' is sent before a 'focus'
return;
}
textAreaState.applyToTextArea(reason, this._textArea, this._hasFocus || forceFocus);
this._textAreaState = textAreaState;
}
// ------------- Operations that are always executed asynchronously
......@@ -322,14 +304,8 @@ export class TextAreaHandler extends Disposable {
if (txt === '') {
return;
}
let pasteOnNewLine = false;
if (browser.enableEmptySelectionClipboard) {
pasteOnNewLine = (txt === this.lastCopiedValue && this.lastCopiedValueIsFromEmptySelection);
}
this._onPaste.fire({
text: txt,
pasteOnNewLine: pasteOnNewLine
text: txt
});
}
......@@ -338,13 +314,13 @@ export class TextAreaHandler extends Disposable {
}
private _writePlaceholderAndSelectTextArea(reason: string, forceFocus: boolean): void {
if (!this.textareaIsShownAtCursor) {
if (!this._isDoingComposition) {
// Do not write to the textarea if it is visible.
if (browser.isIPad) {
// Do not place anything in the textarea for the iPad
this.setTextAreaState(reason, this.textAreaState.toEmpty(), forceFocus);
this.setTextAreaState(reason, this._textAreaState.toEmpty(), forceFocus);
} else {
this.setTextAreaState(reason, this.textAreaState.fromEditorSelection(this.model, this.selection), forceFocus);
this.setTextAreaState(reason, this._textAreaState.fromEditorSelection(this._model, this._selection), forceFocus);
}
}
}
......@@ -352,28 +328,15 @@ export class TextAreaHandler extends Disposable {
// ------------- Clipboard operations
private _ensureClipboardGetsEditorSelection(e: ClipboardEvent): void {
let whatToCopy = this.model.getPlainTextToCopy(this.selections, browser.enableEmptySelectionClipboard);
let whatToCopy = this._host.getPlainTextToCopy();
if (ClipboardEventUtils.canUseTextData(e)) {
let whatHTMLToCopy: string = null;
if (!browser.isEdgeOrIE && (whatToCopy.length < 65536 || CopyOptions.forceCopyWithSyntaxHighlighting)) {
whatHTMLToCopy = this.model.getHTMLToCopy(this.selections, browser.enableEmptySelectionClipboard);
whatHTMLToCopy = this._host.getHTMLToCopy();
}
ClipboardEventUtils.setTextData(e, whatToCopy, whatHTMLToCopy);
} else {
this.setTextAreaState('copy or cut', this.textAreaState.fromText(whatToCopy), false);
}
if (browser.enableEmptySelectionClipboard) {
if (browser.isFirefox) {
// When writing "LINE\r\n" to the clipboard and then pasting,
// Firefox pastes "LINE\n", so let's work around this quirk
this.lastCopiedValue = whatToCopy.replace(/\r\n/g, '\n');
} else {
this.lastCopiedValue = whatToCopy;
}
let selections = this.selections;
this.lastCopiedValueIsFromEmptySelection = (selections.length === 1 && selections[0].isEmpty());
this.setTextAreaState('copy or cut', this._textAreaState.fromText(whatToCopy), false);
}
}
}
......
......@@ -7,7 +7,6 @@
import { commonPrefixLength, commonSuffixLength } from 'vs/base/common/strings';
import { Range } from 'vs/editor/common/core/range';
import { EndOfLinePreference } from 'vs/editor/common/editorCommon';
import { Position } from 'vs/editor/common/core/position';
import { Constants } from 'vs/editor/common/core/uint';
export interface ITextAreaWrapper {
......@@ -21,17 +20,9 @@ export interface ITextAreaWrapper {
}
export interface ISimpleModel {
getLineCount(): number;
getLineMaxColumn(lineNumber: number): number;
getEOL(): string;
getValueInRange(range: Range, eol: EndOfLinePreference): string;
getModelLineContent(lineNumber: number): string;
getLineCount(): number;
getPlainTextToCopy(ranges: Range[], enableEmptySelectionClipboard: boolean): string;
getHTMLToCopy(ranges: Range[], enableEmptySelectionClipboard: boolean): string;
coordinatesConverter: {
convertViewPositionToModelPosition(viewPosition: Position): Position;
};
}
export interface ITypeData {
......
......@@ -112,10 +112,8 @@ export interface IViewModel {
getLineMaxColumn(lineNumber: number): number;
getLineRenderLineNumber(lineNumber: number): string;
getAllOverviewRulerDecorations(): ViewModelDecoration[];
getEOL(): string;
getValueInRange(range: Range, eol: EndOfLinePreference): string;
getModelLineContent(modelLineNumber: number): string;
getModelLineMaxColumn(modelLineNumber: number): number;
validateModelPosition(modelPosition: IPosition): Position;
......
......@@ -539,19 +539,11 @@ export class ViewModel extends Disposable implements IViewModel {
return this.decorations.getAllOverviewRulerDecorations();
}
public getEOL(): string {
return this.model.getEOL();
}
public getValueInRange(range: Range, eol: editorCommon.EndOfLinePreference): string {
var modelRange = this.coordinatesConverter.convertViewRangeToModelRange(range);
return this.model.getValueInRange(modelRange, eol);
}
public getModelLineContent(modelLineNumber: number): string {
return this.model.getLineContent(modelLineNumber);
}
public getModelLineMaxColumn(modelLineNumber: number): number {
return this.model.getLineMaxColumn(modelLineNumber);
}
......@@ -561,7 +553,7 @@ export class ViewModel extends Disposable implements IViewModel {
}
public getPlainTextToCopy(ranges: Range[], enableEmptySelectionClipboard: boolean): string {
let newLineCharacter = this.getEOL();
let newLineCharacter = this.model.getEOL();
if (ranges.length === 1) {
let range: Range = ranges[0];
......
......@@ -4,11 +4,10 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TextAreaHandler } from 'vs/editor/browser/controller/textAreaHandler';
import { TextAreaHandler, ITextAreaHandlerHost } from 'vs/editor/browser/controller/textAreaHandler';
import { TextAreaStrategy, ISimpleModel } from 'vs/editor/browser/controller/textAreaState';
import { Range, IRange } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { Position } from 'vs/editor/common/core/position';
import { createFastDomNode } from 'vs/base/browser/fastDomNode';
// To run this test, open imeTester.html
......@@ -18,18 +17,12 @@ class SingleLineTestModel implements ISimpleModel {
private _line: string;
private _eol: string;
public coordinatesConverter = {
convertViewPositionToModelPosition: (viewPosition: Position): Position => {
return viewPosition;
}
};
constructor(line: string) {
this._line = line;
this._eol = '\n';
}
setText(text: string) {
_setText(text: string) {
this._line = text;
}
......@@ -37,10 +30,6 @@ class SingleLineTestModel implements ISimpleModel {
return this._line.length + 1;
}
getEOL(): string {
return this._eol;
}
getValueInRange(range: IRange, eol: editorCommon.EndOfLinePreference): string {
return this._line.substring(range.startColumn - 1, range.endColumn - 1);
}
......@@ -52,14 +41,6 @@ class SingleLineTestModel implements ISimpleModel {
getLineCount(): number {
return 1;
}
public getPlainTextToCopy(ranges: Range[], enableEmptySelectionClipboard: boolean): string {
return '';
}
public getHTMLToCopy(ranges: Range[], enableEmptySelectionClipboard: boolean): string {
return '';
}
}
class TestView {
......@@ -101,7 +82,12 @@ function doCreateTest(strategy: TextAreaStrategy, description: string, inputStr:
let model = new SingleLineTestModel('some text');
let handler = new TextAreaHandler(strategy, createFastDomNode(input), model);
const textAreaHandlerHost: ITextAreaHandlerHost = {
getPlainTextToCopy: (): string => '',
getHTMLToCopy: (): string => ''
};
let handler = new TextAreaHandler(textAreaHandlerHost, strategy, createFastDomNode(input), model);
input.onfocus = () => {
handler.setHasFocus(true);
......@@ -135,7 +121,7 @@ function doCreateTest(strategy: TextAreaStrategy, description: string, inputStr:
};
let updateModelAndPosition = (text: string, off: number, len: number) => {
model.setText(text);
model._setText(text);
updatePosition(off, len);
view.paint(output);
......
......@@ -6,7 +6,6 @@
import * as assert from 'assert';
import { IENarratorTextAreaState, ISimpleModel, TextAreaState, ITextAreaWrapper } from 'vs/editor/browser/controller/textAreaState';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { EndOfLinePreference } from 'vs/editor/common/editorCommon';
import { Disposable } from 'vs/base/common/lifecycle';
......@@ -466,12 +465,6 @@ class SimpleModel implements ISimpleModel {
private _lines: string[];
private _eol: string;
public coordinatesConverter = {
convertViewPositionToModelPosition: (viewPosition: Position): Position => {
return viewPosition;
}
};
constructor(lines: string[], eol: string) {
this._lines = lines;
this._eol = eol;
......@@ -493,10 +486,6 @@ class SimpleModel implements ISimpleModel {
throw new Error('Unknown EOL preference');
}
public getEOL(): string {
return this._eol;
}
public getValueInRange(range: Range, eol: EndOfLinePreference): string {
if (Range.isEmpty(range)) {
return '';
......@@ -520,19 +509,7 @@ class SimpleModel implements ISimpleModel {
return resultLines.join(lineEnding);
}
public getModelLineContent(lineNumber: number): string {
return this._lines[lineNumber - 1];
}
public getLineCount(): number {
return this._lines.length;
}
public getPlainTextToCopy(ranges: Range[], enableEmptySelectionClipboard: boolean): string {
return '';
}
public getHTMLToCopy(ranges: Range[], enableEmptySelectionClipboard: boolean): string {
return '';
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册