]> git.proxmox.com Git - mirror_xterm.js.git/blame - src/SelectionManager.ts
Handle scrolling of selection
[mirror_xterm.js.git] / src / SelectionManager.ts
CommitLineData
70fda994
DI
1/**
2 * @license MIT
3 */
4
5import { CharMeasure } from './utils/CharMeasure';
6import { CircularList } from './utils/CircularList';
b594407c 7import { EventEmitter } from './EventEmitter';
70fda994 8import * as Mouse from './utils/Mouse';
ad3ae67e 9import { ITerminal } from './Interfaces';
70fda994 10
b594407c
DI
11export class SelectionManager extends EventEmitter {
12 // TODO: Create a SelectionModel
70fda994
DI
13 private _selectionStart: [number, number];
14 private _selectionEnd: [number, number];
15
70fda994
DI
16 private _mouseMoveListener: EventListener;
17
ad3ae67e
DI
18 constructor(
19 private _terminal: ITerminal,
20 private _buffer: CircularList<any>,
21 private _rowContainer: HTMLElement,
22 private _selectionContainer: HTMLElement,
23 private _charMeasure: CharMeasure
24 ) {
b594407c 25 super();
70fda994
DI
26 this._attachListeners();
27 }
28
29 private _attachListeners() {
30 this._mouseMoveListener = event => this._onMouseMove(<MouseEvent>event);
31
32 this._buffer.on('trim', amount => this._onTrim(amount));
33 this._rowContainer.addEventListener('mousedown', event => this._onMouseDown(event));
34 this._rowContainer.addEventListener('mouseup', event => this._onMouseUp(event));
35 }
36
37 public get selectionText(): string {
38 if (!this._selectionStart || !this._selectionEnd) {
39 return null;
40 }
41 return '';
42 }
43
207c4cf9
DI
44 /**
45 * Redraws the selection.
46 */
47 public refresh(): void {
b594407c
DI
48 // TODO: Figure out when to refresh the selection vs when to refresh the viewport
49 this.emit('refresh', { start: this._selectionStart, end: this._selectionEnd });
207c4cf9
DI
50 }
51
52 /**
53 * Handle the buffer being trimmed, adjust the selection position.
54 * @param amount The amount the buffer is being trimmed.
55 */
70fda994 56 private _onTrim(amount: number) {
b36d8780
DI
57 // TODO: Somehow map the selection coordinates with the list that is constantly being trimmed
58 // Maybe we need an ID in the CircularList that starts from 0 for the first entry and increments
70fda994 59 console.log('trimmed: ' + amount);
207c4cf9
DI
60
61 // Adjust the selection position based on the trimmed amount.
62 this._selectionStart[0] -= amount;
63 this._selectionEnd[0] -= amount;
64
65 // The selection has moved off the buffer, clear it.
66 if (this._selectionEnd[0] < 0) {
67 this._selectionStart = null;
68 this._selectionEnd = null;
69 this.refresh();
70 return;
71 }
72
73 // If the selection start is trimmed, ensure the start column is 0.
74 if (this._selectionStart[0] < 0) {
75 this._selectionStart[1] = 0;
76 }
77
78 // Maybe SelectionManager could maintain it's own ID concept from 0 (top of
79 // buffer) to n (size of buffer). On trim just increment the selection if
80 // necessary. This would reduce complexity and potentially not need the
70fda994
DI
81 }
82
b36d8780 83 private _getMouseBufferCoords(event: MouseEvent) {
ad3ae67e
DI
84 const coords = Mouse.getCoords(event, this._rowContainer, this._charMeasure);
85 // Convert to 0-based
86 coords[0]--;
87 coords[1]--;
88 // Convert viewport coords to buffer coords
89 coords[1] += this._terminal.ydisp;
90 return coords;
b36d8780
DI
91 }
92
70fda994 93 private _onMouseDown(event: MouseEvent) {
b36d8780 94 this._selectionStart = this._getMouseBufferCoords(event);
70fda994 95 if (this._selectionStart) {
ad3ae67e 96 this._selectionEnd = null;
70fda994 97 this._rowContainer.addEventListener('mousemove', this._mouseMoveListener);
ad3ae67e 98 this.refresh();
70fda994
DI
99 }
100 }
101
102 private _onMouseMove(event: MouseEvent) {
b36d8780 103 this._selectionEnd = this._getMouseBufferCoords(event);
207c4cf9
DI
104 // TODO: Only draw here if the selection changes
105 this.refresh();
70fda994
DI
106 }
107
108 private _onMouseUp(event: MouseEvent) {
109 console.log('mouseup');
110 console.log('start', this._selectionStart);
111 console.log('end', this._selectionEnd);
112 if (!this._selectionStart) {
113 return;
114 }
115 this._rowContainer.removeEventListener('mousemove', this._mouseMoveListener);
116 }
117}