Merge pull request #2238 from Tyriar/selection_layering

Move SelectionModel to browser
This commit is contained in:
Daniel Imms
2019-06-15 23:34:39 -07:00
committed by GitHub
5 changed files with 41 additions and 64 deletions
+4 -9
View File
@@ -5,13 +5,12 @@
import { assert } from 'chai'; import { assert } from 'chai';
import { SelectionManager, SelectionMode } from './SelectionManager'; import { SelectionManager, SelectionMode } from './SelectionManager';
import { SelectionModel } from './SelectionModel'; import { SelectionModel } from 'browser/selection/SelectionModel';
import { BufferSet } from 'common/buffer/BufferSet';
import { ITerminal } from './Types'; import { ITerminal } from './Types';
import { IBuffer } from 'common/buffer/Types'; import { IBuffer } from 'common/buffer/Types';
import { IBufferLine } from 'common/Types'; import { IBufferLine } from 'common/Types';
import { MockTerminal } from './TestUtils.test'; import { MockTerminal } from './TestUtils.test';
import { MockOptionsService, MockBufferService } from 'common/TestUtils.test'; import { MockBufferService } from 'common/TestUtils.test';
import { BufferLine } from 'common/buffer/BufferLine'; import { BufferLine } from 'common/buffer/BufferLine';
import { IBufferService } from 'common/services/Services'; import { IBufferService } from 'common/services/Services';
import { MockCharSizeService, MockMouseService } from 'browser/TestUtils.test'; import { MockCharSizeService, MockMouseService } from 'browser/TestUtils.test';
@@ -52,10 +51,7 @@ describe('SelectionManager', () => {
beforeEach(() => { beforeEach(() => {
terminal = new TestMockTerminal(); terminal = new TestMockTerminal();
bufferService = new MockBufferService(20, 20); bufferService = new MockBufferService(20, 20);
terminal.buffers = new BufferSet( terminal.buffers = bufferService.buffers;
new MockOptionsService({ scrollback: 100 }),
bufferService
);
terminal.cols = 20; terminal.cols = 20;
terminal.rows = 20; terminal.rows = 20;
terminal.buffer = terminal.buffers.active; terminal.buffer = terminal.buffers.active;
@@ -366,14 +362,13 @@ describe('SelectionManager', () => {
describe('selectAll', () => { describe('selectAll', () => {
it('should select the entire buffer, beyond the viewport', () => { it('should select the entire buffer, beyond the viewport', () => {
buffer.lines.length = 5; bufferService.resize(20, 5);
buffer.lines.set(0, stringToRow('1')); buffer.lines.set(0, stringToRow('1'));
buffer.lines.set(1, stringToRow('2')); buffer.lines.set(1, stringToRow('2'));
buffer.lines.set(2, stringToRow('3')); buffer.lines.set(2, stringToRow('3'));
buffer.lines.set(3, stringToRow('4')); buffer.lines.set(3, stringToRow('4'));
buffer.lines.set(4, stringToRow('5')); buffer.lines.set(4, stringToRow('5'));
selectionManager.selectAll(); selectionManager.selectAll();
terminal.buffer.ybase = buffer.lines.length - bufferService.rows;
assert.equal(selectionManager.selectionText, '1\n2\n3\n4\n5'); assert.equal(selectionManager.selectionText, '1\n2\n3\n4\n5');
}); });
}); });
+2 -2
View File
@@ -7,7 +7,7 @@ import { ITerminal, ISelectionManager, ISelectionRedrawRequestEvent } from './Ty
import { IBuffer } from 'common/buffer/Types'; import { IBuffer } from 'common/buffer/Types';
import { IBufferLine } from 'common/Types'; import { IBufferLine } from 'common/Types';
import * as Browser from 'common/Platform'; import * as Browser from 'common/Platform';
import { SelectionModel } from './SelectionModel'; import { SelectionModel } from 'browser/selection/SelectionModel';
import { AltClickHandler } from './handlers/AltClickHandler'; import { AltClickHandler } from './handlers/AltClickHandler';
import { CellData } from 'common/buffer/CellData'; import { CellData } from 'common/buffer/CellData';
import { IDisposable } from 'xterm'; import { IDisposable } from 'xterm';
@@ -126,7 +126,7 @@ export class SelectionManager implements ISelectionManager {
this._initListeners(); this._initListeners();
this.enable(); this.enable();
this._model = new SelectionModel(_terminal, bufferService); this._model = new SelectionModel(bufferService);
this._activeSelectionMode = SelectionMode.NORMAL; this._activeSelectionMode = SelectionMode.NORMAL;
} }
@@ -4,36 +4,15 @@
*/ */
import { assert } from 'chai'; import { assert } from 'chai';
import { ITerminal } from './Types';
import { SelectionModel } from './SelectionModel'; import { SelectionModel } from './SelectionModel';
import { BufferSet } from 'common/buffer/BufferSet'; import { MockBufferService } from 'common/TestUtils.test';
import { MockTerminal } from './TestUtils.test';
import { MockOptionsService, MockBufferService } from 'common/TestUtils.test';
import { IBufferService } from 'common/services/Services';
class TestSelectionModel extends SelectionModel { describe('SelectionModel', () => {
constructor( let model: SelectionModel;
terminal: ITerminal,
bufferService: IBufferService
) {
super(terminal, bufferService);
}
}
describe('SelectionManager', () => {
let terminal: ITerminal;
let model: TestSelectionModel;
beforeEach(() => { beforeEach(() => {
terminal = new MockTerminal();
const bufferService = new MockBufferService(80, 2); const bufferService = new MockBufferService(80, 2);
terminal.buffers = new BufferSet( model = new SelectionModel(bufferService);
new MockOptionsService({ scrollback: 10 }),
bufferService
);
terminal.buffer = terminal.buffers.active;
model = new TestSelectionModel(terminal, bufferService);
}); });
describe('clearSelection', () => { describe('clearSelection', () => {
@@ -43,8 +22,8 @@ describe('SelectionManager', () => {
assert.deepEqual(model.finalSelectionStart, [0, 0]); assert.deepEqual(model.finalSelectionStart, [0, 0]);
assert.deepEqual(model.finalSelectionEnd, [10, 2]); assert.deepEqual(model.finalSelectionEnd, [10, 2]);
model.clearSelection(); model.clearSelection();
assert.deepEqual(model.finalSelectionStart, null); assert.deepEqual(model.finalSelectionStart, undefined);
assert.deepEqual(model.finalSelectionEnd, null); assert.deepEqual(model.finalSelectionEnd, undefined);
}); });
}); });
@@ -82,8 +61,8 @@ describe('SelectionManager', () => {
model.selectionStart = [0, 0]; model.selectionStart = [0, 0];
model.selectionEnd = [10, 0]; model.selectionEnd = [10, 0];
model.onTrim(1); model.onTrim(1);
assert.deepEqual(model.finalSelectionStart, null); assert.deepEqual(model.finalSelectionStart, undefined);
assert.deepEqual(model.finalSelectionEnd, null); assert.deepEqual(model.finalSelectionEnd, undefined);
}); });
}); });
@@ -111,9 +90,9 @@ describe('SelectionManager', () => {
assert.deepEqual(model.finalSelectionEnd, [80, 1]); assert.deepEqual(model.finalSelectionEnd, [80, 1]);
}); });
it('should return null if there is no selection start', () => { it('should return null if there is no selection start', () => {
assert.equal(model.finalSelectionEnd, null); assert.equal(model.finalSelectionEnd, undefined);
model.selectionEnd = [1, 2]; model.selectionEnd = [1, 2];
assert.equal(model.finalSelectionEnd, null); assert.equal(model.finalSelectionEnd, undefined);
}); });
it('should return selection start + length if there is no selection end', () => { it('should return selection start + length if there is no selection end', () => {
model.selectionStart = [2, 2]; model.selectionStart = [2, 2];
@@ -3,7 +3,6 @@
* @license MIT * @license MIT
*/ */
import { ITerminal } from './Types';
import { IBufferService } from 'common/services/Services'; import { IBufferService } from 'common/services/Services';
/** /**
@@ -14,38 +13,36 @@ export class SelectionModel {
/** /**
* Whether select all is currently active. * Whether select all is currently active.
*/ */
public isSelectAllActive: boolean; public isSelectAllActive: boolean = false;
/**
* The [x, y] position the selection starts at.
*/
public selectionStart: [number, number];
/** /**
* The minimal length of the selection from the start position. When double * The minimal length of the selection from the start position. When double
* clicking on a word, the word will be selected which makes the selection * clicking on a word, the word will be selected which makes the selection
* start at the start of the word and makes this variable the length. * start at the start of the word and makes this variable the length.
*/ */
public selectionStartLength: number; public selectionStartLength: number = 0;
/**
* The [x, y] position the selection starts at.
*/
public selectionStart: [number, number] | undefined;
/** /**
* The [x, y] position the selection ends at. * The [x, y] position the selection ends at.
*/ */
public selectionEnd: [number, number]; public selectionEnd: [number, number] | undefined;
constructor( constructor(
private _terminal: ITerminal,
private _bufferService: IBufferService private _bufferService: IBufferService
) { ) {
this.clearSelection();
} }
/** /**
* Clears the current selection. * Clears the current selection.
*/ */
public clearSelection(): void { public clearSelection(): void {
this.selectionStart = null; this.selectionStart = undefined;
this.selectionEnd = null; this.selectionEnd = undefined;
this.isSelectAllActive = false; this.isSelectAllActive = false;
this.selectionStartLength = 0; this.selectionStartLength = 0;
} }
@@ -53,7 +50,7 @@ export class SelectionModel {
/** /**
* The final selection start, taking into consideration select all. * The final selection start, taking into consideration select all.
*/ */
public get finalSelectionStart(): [number, number] { public get finalSelectionStart(): [number, number] | undefined {
if (this.isSelectAllActive) { if (this.isSelectAllActive) {
return [0, 0]; return [0, 0];
} }
@@ -69,13 +66,13 @@ export class SelectionModel {
* The final selection end, taking into consideration select all, double click * The final selection end, taking into consideration select all, double click
* word selection and triple click line selection. * word selection and triple click line selection.
*/ */
public get finalSelectionEnd(): [number, number] { public get finalSelectionEnd(): [number, number] | undefined {
if (this.isSelectAllActive) { if (this.isSelectAllActive) {
return [this._bufferService.cols, this._terminal.buffer.ybase + this._bufferService.rows - 1]; return [this._bufferService.cols, this._bufferService.buffer.ybase + this._bufferService.rows - 1];
} }
if (!this.selectionStart) { if (!this.selectionStart) {
return null; return undefined;
} }
// Use the selection start + length if the end doesn't exist or they're reversed // Use the selection start + length if the end doesn't exist or they're reversed
+11 -5
View File
@@ -8,14 +8,18 @@ import { IEvent, EventEmitter } from 'common/EventEmitter';
import { clone } from 'common/Clone'; import { clone } from 'common/Clone';
import { DEFAULT_OPTIONS } from 'common/services/OptionsService'; import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
import { IBufferSet, IBuffer } from 'common/buffer/Types'; import { IBufferSet, IBuffer } from 'common/buffer/Types';
import { BufferSet } from 'common/buffer/BufferSet';
export class MockBufferService implements IBufferService { export class MockBufferService implements IBufferService {
public buffer: IBuffer = {} as any; public get buffer(): IBuffer { return this.buffers.active; }
public buffers: IBufferSet = {} as any; public buffers: IBufferSet = {} as any;
constructor( constructor(
public cols: number, public cols: number,
public rows: number public rows: number,
) {} optionsService: IOptionsService = new MockOptionsService()
) {
this.buffers = new BufferSet(optionsService, this);
}
resize(cols: number, rows: number): void { resize(cols: number, rows: number): void {
this.cols = cols; this.cols = cols;
this.rows = rows; this.rows = rows;
@@ -26,8 +30,10 @@ export class MockBufferService implements IBufferService {
export class MockOptionsService implements IOptionsService { export class MockOptionsService implements IOptionsService {
options: ITerminalOptions = clone(DEFAULT_OPTIONS); options: ITerminalOptions = clone(DEFAULT_OPTIONS);
onOptionChange: IEvent<string> = new EventEmitter<string>().event; onOptionChange: IEvent<string> = new EventEmitter<string>().event;
constructor(testOptions: IPartialTerminalOptions) { constructor(testOptions?: IPartialTerminalOptions) {
Object.keys(testOptions).forEach(key => this.options[key] = (<any>testOptions)[key]); if (testOptions) {
Object.keys(testOptions).forEach(key => this.options[key] = (<any>testOptions)[key]);
}
} }
setOption<T>(key: string, value: T): void { setOption<T>(key: string, value: T): void {
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');