]>
Commit | Line | Data |
---|---|---|
70fda994 DI |
1 | /** |
2 | * @license MIT | |
3 | */ | |
4 | ||
5 | import { CharMeasure } from './utils/CharMeasure'; | |
6 | import { CircularList } from './utils/CircularList'; | |
b594407c | 7 | import { EventEmitter } from './EventEmitter'; |
70fda994 | 8 | import * as Mouse from './utils/Mouse'; |
ad3ae67e | 9 | import { ITerminal } from './Interfaces'; |
70fda994 | 10 | |
b594407c DI |
11 | export 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 | } |