UNPKG

7.35 kBJavaScriptView Raw
1/*
2 Terminal Kit
3
4 Copyright (c) 2009 - 2020 Cédric Ronvel
5
6 The MIT License (MIT)
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in all
16 copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 SOFTWARE.
25*/
26
27"use strict" ;
28
29
30
31const TextBox = require( './TextBox.js' ) ;
32const string = require( 'string-kit' ) ;
33
34
35
36function EditableTextBox( options ) {
37 // Clone options if necessary
38 options = ! options ? {} : options.internal ? options : Object.create( options ) ;
39 options.internal = true ;
40
41 if ( options.value ) { options.content = options.value ; }
42
43 TextBox.call( this , options ) ;
44
45 this.onKey = this.onKey.bind( this ) ;
46 this.onFocus = this.onFocus.bind( this ) ;
47 //this.onClick = this.onClick.bind( this ) ;
48 this.onMiddleClick = this.onMiddleClick.bind( this ) ;
49
50 if ( options.keyBindings ) { this.keyBindings = options.keyBindings ; }
51
52 // Editable textbox get extraScrolling by default
53 this.extraScrolling = options.extraScrolling !== undefined ? !! options.extraScrolling : true ;
54
55 this.updateStatus() ;
56
57 this.on( 'key' , this.onKey ) ;
58 this.on( 'focus' , this.onFocus ) ;
59 //this.on( 'click' , this.onClick ) ;
60 this.on( 'middleClick' , this.onMiddleClick ) ;
61
62 // Only draw if we are not a superclass of the object
63 if ( this.elementType === 'EditableTextBox' && ! options.noDraw ) { this.draw() ; }
64}
65
66module.exports = EditableTextBox ;
67
68EditableTextBox.prototype = Object.create( TextBox.prototype ) ;
69EditableTextBox.prototype.constructor = EditableTextBox ;
70EditableTextBox.prototype.elementType = 'EditableTextBox' ;
71
72
73
74EditableTextBox.prototype.destroy = function( isSubDestroy ) {
75 this.off( 'key' , this.onKey ) ;
76 this.off( 'focus' , this.onFocus ) ;
77 //this.off( 'click' , this.onClick ) ;
78 this.off( 'middleClick' , this.onMiddleClick ) ;
79
80 TextBox.prototype.destroy.call( this , isSubDestroy ) ;
81} ;
82
83
84
85EditableTextBox.prototype.keyBindings = {
86 ENTER: 'newLine' ,
87 KP_ENTER: 'newLine' ,
88 BACKSPACE: 'backDelete' ,
89 DELETE: 'delete' ,
90 LEFT: 'backward' ,
91 RIGHT: 'forward' ,
92 CTRL_LEFT: 'startOfWord' ,
93 CTRL_RIGHT: 'endOfWord' ,
94 UP: 'up' ,
95 DOWN: 'down' ,
96 HOME: 'startOfLine' ,
97 END: 'endOfLine' ,
98 TAB: 'tab' ,
99 PAGE_UP: 'scrollUp' ,
100 PAGE_DOWN: 'scrollDown' ,
101 CTRL_O: 'copyClipboard' ,
102 CTRL_P: 'pasteClipboard'
103} ;
104
105
106
107EditableTextBox.prototype.drawSelfCursor = function() {
108 this.textBuffer.drawCursor() ;
109} ;
110
111
112
113EditableTextBox.prototype.getValue = TextBox.prototype.getContent ;
114
115
116
117EditableTextBox.prototype.setValue = function( value , dontDraw ) {
118 return TextBox.prototype.setContent.call( value , false , dontDraw ) ;
119} ;
120
121
122
123EditableTextBox.prototype.onKey = function( key , trash , data ) {
124 var dy ;
125
126 if ( data && data.isCharacter ) {
127 this.textBuffer.insert( key , this.textAttr ) ;
128 this.textBuffer.runStateMachine() ;
129 this.autoScrollAndDraw() ;
130 }
131 else {
132 // Here we have a special key
133
134 switch( this.keyBindings[ key ] ) {
135 case 'newLine' :
136 this.textBuffer.newLine() ;
137 this.textBuffer.runStateMachine() ;
138 this.autoScrollAndDraw() ;
139 break ;
140
141 case 'backDelete' :
142 this.textBuffer.backDelete() ;
143 this.textBuffer.runStateMachine() ;
144 this.autoScrollAndDraw() ;
145 break ;
146
147 case 'delete' :
148 this.textBuffer.delete() ;
149 this.textBuffer.runStateMachine() ;
150 this.autoScrollAndDraw() ;
151 break ;
152
153 case 'backward' :
154 this.textBuffer.moveBackward() ;
155 this.autoScrollAndDrawCursor() ;
156 break ;
157
158 case 'forward' :
159 this.textBuffer.moveForward() ;
160 this.autoScrollAndDrawCursor() ;
161 break ;
162
163 case 'startOfWord' :
164 this.textBuffer.moveToStartOfWord() ;
165 this.autoScrollAndDrawCursor() ;
166 break ;
167
168 case 'endOfWord' :
169 this.textBuffer.moveToEndOfWord() ;
170 this.autoScrollAndDrawCursor() ;
171 break ;
172
173 case 'startOfLine' :
174 this.textBuffer.moveToColumn( 0 ) ;
175 this.autoScrollAndDrawCursor() ;
176 break ;
177
178 case 'endOfLine' :
179 this.textBuffer.moveToEndOfLine() ;
180 this.autoScrollAndDrawCursor() ;
181 break ;
182
183 case 'down' :
184 this.textBuffer.moveDown() ;
185 this.autoScrollAndDrawCursor() ;
186 break ;
187
188 case 'up' :
189 this.textBuffer.moveUp() ;
190 this.autoScrollAndDrawCursor() ;
191 break ;
192
193 case 'left' :
194 this.textBuffer.moveLeft() ;
195 this.autoScrollAndDrawCursor() ;
196 break ;
197
198 case 'right' :
199 this.textBuffer.moveRight() ;
200 this.autoScrollAndDrawCursor() ;
201 break ;
202
203 case 'tab' :
204 this.textBuffer.insert( '\t' , this.textAttr ) ;
205 this.textBuffer.runStateMachine() ;
206 this.autoScrollAndDraw() ;
207 break ;
208
209 case 'scrollUp' :
210 dy = Math.ceil( this.outputHeight / 2 ) ;
211 this.textBuffer.move( 0 , -dy ) ;
212 this.scroll( 0 , dy ) ;
213 break ;
214
215 case 'scrollDown' :
216 dy = -Math.ceil( this.outputHeight / 2 ) ;
217 this.textBuffer.move( 0 , -dy ) ;
218 this.scroll( 0 , dy ) ;
219 break ;
220
221 case 'pasteClipboard' :
222 if ( this.document ) {
223 this.document.getClipboard().then( str => {
224 if ( str ) {
225 this.textBuffer.insert( str , this.textAttr ) ;
226 this.textBuffer.runStateMachine() ;
227 this.autoScrollAndDraw() ;
228 }
229 } )
230 .catch( () => undefined ) ;
231 }
232 break ;
233
234 case 'copyClipboard' :
235 if ( this.document ) {
236 this.document.setClipboard( this.textBuffer.getSelectionText() ).catch( () => undefined ) ;
237 }
238 break ;
239
240 default :
241 return ; // Bubble up
242 }
243 }
244
245 return true ; // Do not bubble up
246} ;
247
248
249
250EditableTextBox.prototype.onFocus = function( focus , type ) {
251 this.hasFocus = focus ;
252 this.updateStatus() ;
253 this.draw() ;
254} ;
255
256
257
258EditableTextBox.prototype.onClick = function( data ) {
259 if ( ! this.hasFocus ) {
260 this.document.giveFocusTo( this , 'select' ) ;
261 }
262 else {
263 this.textBuffer.moveTo( data.x - this.scrollX , data.y - this.scrollY ) ;
264 this.drawCursor() ;
265 }
266} ;
267
268
269
270EditableTextBox.prototype.onMiddleClick = function( data ) {
271 if ( ! this.hasFocus ) {
272 this.document.giveFocusTo( this , 'select' ) ;
273 }
274
275 // Do not moveTo, it's quite boring
276 //this.textBuffer.moveTo( data.x , data.y ) ;
277
278 if ( this.document ) {
279 this.document.getClipboard( 'primary' ).then( str => {
280 if ( str ) {
281 this.textBuffer.insert( str , this.textAttr ) ;
282 this.textBuffer.runStateMachine() ;
283 this.autoScrollAndDraw() ;
284 }
285 //else { this.drawCursor() ; }
286 } )
287 .catch( () => undefined ) ;
288 }
289 //else { this.drawCursor() ; }
290} ;
291
292
293
294// There isn't much to do ATM
295EditableTextBox.prototype.updateStatus = function() {} ;
296