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

Reduce usage of /browser/ in textAreaHandler

上级 78066066
......@@ -213,7 +213,7 @@ export class KeyboardHandler extends ViewEventHandler implements Lifecycle.IDisp
this.textArea = new TextAreaWrapper(viewHelper.textArea);
this.viewHelper = viewHelper;
this.textAreaHandler = new TextAreaHandler(this.textArea, {
this.textAreaHandler = new TextAreaHandler(Platform, Browser, this.textArea, {
getModel: (): ISimpleModel => this.context.model,
emitKeyDown: (e:IKeyboardEventWrapper): void => this.viewController.emitKeyDown(<DomUtils.IKeyboardEvent>e._actual),
emitKeyUp: (e:IKeyboardEventWrapper): void => this.viewController.emitKeyUp(<DomUtils.IKeyboardEvent>e._actual),
......@@ -256,27 +256,27 @@ export class KeyboardHandler extends ViewEventHandler implements Lifecycle.IDisp
}
public onScrollChanged(e:EditorCommon.IScrollEvent): boolean {
this.textAreaHandler.onScrollChanged(e);
this.textAreaHandler.setScrollLeft(e.scrollLeft);
return false;
}
public onViewFocusChanged(isFocused:boolean): boolean {
this.textAreaHandler.onViewFocusChanged(isFocused);
this.textAreaHandler.setHasFocus(isFocused);
return false;
}
public onCursorSelectionChanged(e:EditorCommon.IViewCursorSelectionChangedEvent): boolean {
this.textAreaHandler.onCursorSelectionChanged(e);
this.textAreaHandler.setCursorSelections(e.selection, e.secondarySelections);
return false;
}
public onCursorPositionChanged(e:EditorCommon.IViewCursorPositionChangedEvent): boolean {
this.textAreaHandler.onCursorPositionChanged(e);
this.textAreaHandler.setCursorPosition(e.position);
return false;
}
public onLayoutChanged(layoutInfo:EditorCommon.IEditorLayoutInfo): boolean {
this.textAreaHandler.onLayoutChanged(layoutInfo);
this.textAreaHandler.setLayoutInfo(layoutInfo.contentLeft, layoutInfo.contentWidth);
return false;
}
......
......@@ -4,17 +4,13 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import EditorCommon = require('vs/editor/common/editorCommon');
import Platform = require('vs/base/common/platform');
import Browser = require('vs/base/browser/browser');
import EditorBrowser = require('vs/editor/browser/editorBrowser');
import Schedulers = require('vs/base/common/async');
import * as Lifecycle from 'vs/base/common/lifecycle';
import Strings = require('vs/base/common/strings');
import {VisibleRange, IConfiguration, IEditorRange, IEditorPosition, EndOfLinePreference} from 'vs/editor/common/editorCommon';
import {RunOnceScheduler} from 'vs/base/common/async';
import {Disposable} from 'vs/base/common/lifecycle';
import {commonPrefixLength, commonSuffixLength} from '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 {IKeyboardEventWrapper, ITextAreaWrapper, IClipboardEvent, ITextAreaStyle, ISimpleModel, TextAreaState} from 'vs/editor/common/controller/textAreaState';
enum ReadFromTextArea {
......@@ -32,27 +28,39 @@ export interface ITextEditor {
replacePreviousChar(source:string, txt:string): void;
cut(source:string): void;
visibleRangeForPositionRelativeToEditor(lineNumber:number, column1:number, column2:number): { column1: EditorCommon.VisibleRange; column2: EditorCommon.VisibleRange; };
visibleRangeForPositionRelativeToEditor(lineNumber:number, column1:number, column2:number): { column1: VisibleRange; column2: VisibleRange; };
startIME(): void;
stopIME(): void;
}
export interface IPlatform {
isMacintosh: boolean;
isWindows: boolean;
}
export interface IBrowser {
isIPad: boolean;
isChrome: boolean;
isIE11orEarlier: boolean;
isFirefox: boolean;
enableEmptySelectionClipboard: boolean;
}
export class TextAreaHandler implements Lifecycle.IDisposable {
export class TextAreaHandler extends Disposable {
private Platform:IPlatform;
private Browser:IBrowser;
private textArea:ITextAreaWrapper;
private editor:ITextEditor;
private configuration:EditorCommon.IConfiguration;
private configuration:IConfiguration;
private selection:EditorCommon.IEditorRange;
private selections:EditorCommon.IEditorRange[];
private selection:IEditorRange;
private selections:IEditorRange[];
private hasFocus:boolean;
private _toDispose:Lifecycle.IDisposable[];
private asyncReadFromTextArea: Schedulers.RunOnceScheduler;
private asyncSetSelectionToTextArea: Schedulers.RunOnceScheduler;
private asyncTriggerCut: Schedulers.RunOnceScheduler;
private asyncReadFromTextArea: RunOnceScheduler;
private asyncSetSelectionToTextArea: RunOnceScheduler;
private asyncTriggerCut: RunOnceScheduler;
// keypress, paste & composition end also trigger an input event
// the popover input method on macs triggers only an input event
......@@ -62,7 +70,7 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
private lastKeyPressTime:number;
private lastCompositionEndTime:number;
private lastValueWrittenToTheTextArea:string;
private cursorPosition:EditorCommon.IEditorPosition;
private cursorPosition:IEditorPosition;
private contentLeft:number;
private contentWidth:number;
private scrollLeft:number;
......@@ -73,7 +81,8 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
private lastCopiedValue: string;
private lastCopiedValueIsFromEmptySelection: boolean;
constructor(textArea:ITextAreaWrapper, editor:ITextEditor, configuration:EditorCommon.IConfiguration) {
constructor(Platform:IPlatform, Browser:IBrowser, textArea:ITextAreaWrapper, editor:ITextEditor, configuration:IConfiguration) {
super();
this.textArea = textArea;
this.editor = editor;
this.configuration = configuration;
......@@ -84,9 +93,9 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
this.contentWidth = 0;
this.scrollLeft = 0;
this.asyncReadFromTextArea = new Schedulers.RunOnceScheduler(null, 0);
this.asyncSetSelectionToTextArea = new Schedulers.RunOnceScheduler(() => this._writePlaceholderAndSelectTextArea(), 0);
this.asyncTriggerCut = new Schedulers.RunOnceScheduler(() => this._triggerCut(), 0);
this.asyncReadFromTextArea = new RunOnceScheduler(null, 0);
this.asyncSetSelectionToTextArea = new RunOnceScheduler(() => this._writePlaceholderAndSelectTextArea(), 0);
this.asyncTriggerCut = new RunOnceScheduler(() => this._triggerCut(), 0);
this.lastCopiedValue = null;
this.lastCopiedValueIsFromEmptySelection = false;
......@@ -100,15 +109,13 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
this.lastCompositionEndTime = 0;
this.lastValueWrittenToTheTextArea = '';
this._toDispose = [];
this._toDispose.push(this.textArea.onKeyDown((e) => this._onKeyDown(e)));
this._toDispose.push(this.textArea.onKeyUp((e) => this._onKeyUp(e)));
this._toDispose.push(this.textArea.onKeyPress((e) => this._onKeyPress()));
this._register(this.textArea.onKeyDown((e) => this._onKeyDown(e)));
this._register(this.textArea.onKeyUp((e) => this._onKeyUp(e)));
this._register(this.textArea.onKeyPress((e) => this._onKeyPress()));
this.textareaIsShownAtCursor = false;
this._toDispose.push(this.textArea.onCompositionStart(() => {
this._register(this.textArea.onCompositionStart(() => {
let timeSinceLastCompositionEnd = (new Date().getTime()) - this.lastCompositionEndTime;
if (!this.textareaIsShownAtCursor) {
this.textareaIsShownAtCursor = true;
......@@ -117,7 +124,7 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
this.asyncReadFromTextArea.cancel();
}));
this._toDispose.push(this.textArea.onCompositionEnd(() => {
this._register(this.textArea.onCompositionEnd(() => {
if (this.textareaIsShownAtCursor) {
this.textareaIsShownAtCursor = false;
this.hideTextArea();
......@@ -128,8 +135,8 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
// on the iPad the text area is not fast enough to get the content of the keypress,
// so we leverage the input event instead
if (Browser.isIPad) {
this._toDispose.push(this.textArea.onInput(() => {
if (this.Browser.isIPad) {
this._register(this.textArea.onInput(() => {
let myTime = (new Date()).getTime();
// A keypress will trigger an input event (very quickly)
let keyPressDeltaTime = myTime - this.lastKeyPressTime;
......@@ -142,16 +149,16 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
// on the mac the character viewer input generates an input event (no keypress)
// on windows, the Chinese IME, when set to insert wide punctuation generates an input event (no keypress)
this._toDispose.push(this.textArea.onInput(() => {
this._register(this.textArea.onInput(() => {
// Ignore input event if we are in composition mode
if (!this.textareaIsShownAtCursor) {
this._scheduleReadFromTextArea(ReadFromTextArea.Type);
}
}));
if (Platform.isMacintosh) {
if (this.Platform.isMacintosh) {
this._toDispose.push(this.textArea.onInput(() => {
this._register(this.textArea.onInput(() => {
// We are fishing for the input event that comes in the mac popover input method case
......@@ -196,7 +203,7 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
let typedText:string;
let textAreaValue = this.textArea.value;
if (!Browser.isChrome) {
if (!this.Browser.isChrome) {
// TODO: Also check this on Safari & FF before removing this
return;
}
......@@ -205,8 +212,8 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
return;
}
let prefixLength = Strings.commonPrefixLength(this.lastValueWrittenToTheTextArea, textAreaValue);
let suffixLength = Strings.commonSuffixLength(this.lastValueWrittenToTheTextArea, textAreaValue);
let prefixLength = commonPrefixLength(this.lastValueWrittenToTheTextArea, textAreaValue);
let suffixLength = commonSuffixLength(this.lastValueWrittenToTheTextArea, textAreaValue);
if (prefixLength + suffixLength + 1 !== textAreaValue.length) {
return;
......@@ -221,19 +228,19 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
}));
}
this._toDispose.push(this.textArea.onCut((e) => this._onCut(e)));
this._toDispose.push(this.textArea.onCopy((e) => this._onCopy(e)));
this._toDispose.push(this.textArea.onPaste((e) => this._onPaste(e)));
this._register(this.textArea.onCut((e) => this._onCut(e)));
this._register(this.textArea.onCopy((e) => this._onCopy(e)));
this._register(this.textArea.onPaste((e) => this._onPaste(e)));
this._writePlaceholderAndSelectTextArea();
}
public dispose(): void {
this._toDispose = Lifecycle.disposeAll(this._toDispose);
this.asyncReadFromTextArea.dispose();
this.asyncSetSelectionToTextArea.dispose();
this.asyncTriggerCut.dispose();
super.dispose();
}
private showTextAreaAtCursor(emptyIt:boolean): void {
......@@ -243,7 +250,7 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
interestingColumn2:number;
// In IE we cannot set .value when handling 'compositionstart' because the entire composition will get canceled.
if (Browser.isIE11orEarlier) {
if (this.Browser.isIE11orEarlier) {
// Ensure selection start is in viewport
interestingLineNumber = this.selection.startLineNumber;
interestingColumn1 = this.selection.startColumn;
......@@ -265,7 +272,7 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
width: undefined,
height: undefined
};
if (Browser.isIE11orEarlier) {
if (this.Browser.isIE11orEarlier) {
// Position textarea at the beginning of the line
if (visibleRange1 && visibleRange2) {
style.top = visibleRange1.top + 'px';
......@@ -303,35 +310,30 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
// --- begin event handlers
public onScrollChanged(e:EditorCommon.IScrollEvent): boolean {
this.scrollLeft = e.scrollLeft;
return false;
public setScrollLeft(scrollLeft:number): void {
this.scrollLeft = scrollLeft;
}
public onViewFocusChanged(isFocused:boolean): boolean {
public setHasFocus(isFocused:boolean): void {
this.hasFocus = isFocused;
if (this.hasFocus) {
this.asyncSetSelectionToTextArea.schedule();
}
return false;
}
public onCursorSelectionChanged(e:EditorCommon.IViewCursorSelectionChangedEvent): boolean {
this.selection = e.selection;
this.selections = [e.selection].concat(e.secondarySelections);
public setCursorSelections(primary: IEditorRange, secondary: IEditorRange[]): void {
this.selection = primary;
this.selections = [primary].concat(secondary);
this.asyncSetSelectionToTextArea.schedule();
return false;
}
public onCursorPositionChanged(e:EditorCommon.IViewCursorPositionChangedEvent): boolean {
this.cursorPosition = e.position;
return false;
public setCursorPosition(primary: IEditorPosition): void {
this.cursorPosition = primary;
}
public onLayoutChanged(layoutInfo:EditorCommon.IEditorLayoutInfo): boolean {
this.contentLeft = layoutInfo.contentLeft;
this.contentWidth = layoutInfo.contentWidth;
return false;
public setLayoutInfo(contentLeft:number, contentWidth:number): void {
this.contentLeft = contentLeft;
this.contentWidth = contentWidth;
}
// --- end event handlers
......@@ -393,7 +395,7 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
// on the iPad the text area is not fast enough to get the content of the keypress,
// so we leverage the input event instead
if (!Browser.isIPad) {
if (!this.Browser.isIPad) {
this._scheduleReadFromTextArea(ReadFromTextArea.Type);
}
}
......@@ -433,7 +435,7 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
}
let pasteOnNewLine = false;
if (Browser.enableEmptySelectionClipboard) {
if (this.Browser.enableEmptySelectionClipboard) {
pasteOnNewLine = (txt === this.lastCopiedValue && this.lastCopiedValueIsFromEmptySelection);
}
this.editor.paste('keyboard', txt, pasteOnNewLine);
......@@ -456,7 +458,7 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
// Do not write to the textarea if it is visible.
let previousSelectionToken = this.previousSetTextAreaState ? this.previousSetTextAreaState.getSelectionToken() : 0;
let newState: TextAreaState;
if (Browser.isIPad) {
if (this.Browser.isIPad) {
// Do not place anything in the textarea for the iPad
newState = new TextAreaState('', 0, 0, false, 0);
} else {
......@@ -503,8 +505,8 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
this.setTextAreaState(new TextAreaState(whatToCopy, 0, whatToCopy.length, false, 0), true);
}
if (Browser.enableEmptySelectionClipboard) {
if (Browser.isFirefox) {
if (this.Browser.enableEmptySelectionClipboard) {
if (this.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');
......@@ -518,15 +520,15 @@ export class TextAreaHandler implements Lifecycle.IDisposable {
}
private _getPlainTextToCopy(): string {
let newLineCharacter = (Platform.isWindows ? '\r\n' : '\n');
let eolPref = (Platform.isWindows ? EditorCommon.EndOfLinePreference.CRLF : EditorCommon.EndOfLinePreference.LF);
let newLineCharacter = (this.Platform.isWindows ? '\r\n' : '\n');
let eolPref = (this.Platform.isWindows ? EndOfLinePreference.CRLF : EndOfLinePreference.LF);
let selections = this.selections;
let model = this.editor.getModel();
if (selections.length === 1) {
let range:EditorCommon.IEditorRange = selections[0];
let range:IEditorRange = selections[0];
if (range.isEmpty()) {
if (Browser.enableEmptySelectionClipboard) {
if (this.Browser.enableEmptySelectionClipboard) {
let modelLineNumber = model.convertViewPositionToModelPosition(range.startLineNumber, 1).lineNumber;
return model.getModelLineContent(modelLineNumber) + newLineCharacter;
} else {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册