Add events to TermScreen; use correct cursor
This commit is contained in:
@@ -97,6 +97,9 @@ class TermScreen {
|
|||||||
|
|
||||||
this.mouseMode = { clicks: false, movement: false };
|
this.mouseMode = { clicks: false, movement: false };
|
||||||
|
|
||||||
|
// event listeners
|
||||||
|
this._listeners = {};
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
this.window = new Proxy(this._window, {
|
this.window = new Proxy(this._window, {
|
||||||
set (target, key, value, receiver) {
|
set (target, key, value, receiver) {
|
||||||
@@ -159,21 +162,68 @@ class TermScreen {
|
|||||||
e.deltaY > 0 ? 1 : -1);
|
e.deltaY > 0 ? 1 : -1);
|
||||||
|
|
||||||
// prevent page scrolling
|
// prevent page scrolling
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.canvas.addEventListener('contextmenu', e => {
|
||||||
|
// prevent mouse keys getting stuck
|
||||||
|
e.preventDefault();
|
||||||
|
})
|
||||||
|
|
||||||
// bind ctrl+shift+c to copy
|
// bind ctrl+shift+c to copy
|
||||||
key('⌃+⇧+c', e => {
|
key('⌃+⇧+c', e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.copySelectionToClipboard()
|
this.copySelectionToClipboard()
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
on (event, listener) {
|
||||||
|
if (!this._listeners[event]) this._listeners[event] = [];
|
||||||
|
this._listeners[event].push({ listener });
|
||||||
|
}
|
||||||
|
|
||||||
|
once (event, listener) {
|
||||||
|
if (!this._listeners[event]) this._listeners[event] = [];
|
||||||
|
this._listeners[event].push({ listener, once: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
off (event, listener) {
|
||||||
|
let listeners = this._listeners[event];
|
||||||
|
if (listeners) {
|
||||||
|
for (let i in listeners) {
|
||||||
|
if (listeners[i].listener === listener) {
|
||||||
|
listeners.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit (event, ...args) {
|
||||||
|
let listeners = this._listeners[event];
|
||||||
|
if (listeners) {
|
||||||
|
let remove = [];
|
||||||
|
for (let listener of listeners) {
|
||||||
|
try {
|
||||||
|
listener.listener(...args);
|
||||||
|
if (listener.once) remove.push(listener);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this needs to be done in this roundabout way because for loops
|
||||||
|
// do not like arrays with changing lengths
|
||||||
|
for (let listener of remove) {
|
||||||
|
listeners.splice(listeners.indexOf(listener), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get colors () { return this._colors }
|
get colors () { return this._colors }
|
||||||
set colors (theme) {
|
set colors (theme) {
|
||||||
this._colors = theme;
|
this._colors = theme;
|
||||||
this.scheduleDraw()
|
this.scheduleDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
// schedule a draw in the next tick
|
// schedule a draw in the next tick
|
||||||
@@ -197,6 +247,15 @@ class TermScreen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCellSize () {
|
||||||
|
let charSize = this.getCharSize();
|
||||||
|
|
||||||
|
return {
|
||||||
|
width: Math.ceil(charSize.width * this.window.gridScaleX),
|
||||||
|
height: Math.ceil(charSize.height * this.window.gridScaleY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateSize () {
|
updateSize () {
|
||||||
this._window.devicePixelRatio = window.devicePixelRatio || 1;
|
this._window.devicePixelRatio = window.devicePixelRatio || 1;
|
||||||
|
|
||||||
@@ -212,15 +271,12 @@ class TermScreen {
|
|||||||
const {
|
const {
|
||||||
width, height, devicePixelRatio, gridScaleX, gridScaleY
|
width, height, devicePixelRatio, gridScaleX, gridScaleY
|
||||||
} = this.window;
|
} = this.window;
|
||||||
const charSize = this.getCharSize();
|
const cellSize = this.getCellSize();
|
||||||
|
|
||||||
this.canvas.width = width * devicePixelRatio * charSize.width * gridScaleX;
|
this.canvas.width = width * devicePixelRatio * cellSize.width;
|
||||||
this.canvas.style.width = `${Math.ceil(width * charSize.width *
|
this.canvas.style.width = `${width * cellSize.width}px`;
|
||||||
gridScaleX)}px`;
|
this.canvas.height = height * devicePixelRatio * cellSize.height;
|
||||||
this.canvas.height = height * devicePixelRatio * charSize.height *
|
this.canvas.style.height = `${height * cellSize.height}px`
|
||||||
gridScaleY;
|
|
||||||
this.canvas.style.height = `${Math.ceil(height * charSize.height *
|
|
||||||
gridScaleY)}px`
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,16 +367,20 @@ class TermScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
screenToGrid (x, y) {
|
screenToGrid (x, y) {
|
||||||
let charSize = this.getCharSize();
|
let cellSize = this.getCellSize();
|
||||||
let cellWidth = charSize.width * this.window.gridScaleX;
|
|
||||||
let cellHeight = charSize.height * this.window.gridScaleY;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
Math.floor((x + cellWidth / 2) / cellWidth),
|
Math.floor((x + cellSize.width / 2) / cellSize.width),
|
||||||
Math.floor(y / cellHeight)
|
Math.floor(y / cellSize.height)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gridToScreen (x, y) {
|
||||||
|
let cellSize = this.getCellSize();
|
||||||
|
|
||||||
|
return [ x * cellSize.width, y * cellSize.height ];
|
||||||
|
}
|
||||||
|
|
||||||
drawCell ({ x, y, charSize, cellWidth, cellHeight, text, fg, bg, attrs },
|
drawCell ({ x, y, charSize, cellWidth, cellHeight, text, fg, bg, attrs },
|
||||||
compositeAbove = false) {
|
compositeAbove = false) {
|
||||||
const ctx = this.ctx;
|
const ctx = this.ctx;
|
||||||
@@ -377,8 +437,7 @@ class TermScreen {
|
|||||||
} = this.window;
|
} = this.window;
|
||||||
|
|
||||||
const charSize = this.getCharSize();
|
const charSize = this.getCharSize();
|
||||||
const cellWidth = charSize.width * gridScaleX;
|
const { width: cellWidth, height: cellHeight } = this.getCellSize();
|
||||||
const cellHeight = charSize.height * gridScaleY;
|
|
||||||
const screenWidth = width * cellWidth;
|
const screenWidth = width * cellWidth;
|
||||||
const screenHeight = height * cellHeight;
|
const screenHeight = height * cellHeight;
|
||||||
const screenLength = width * height;
|
const screenLength = width * height;
|
||||||
@@ -456,7 +515,10 @@ class TermScreen {
|
|||||||
this.cursor.x = cursorX;
|
this.cursor.x = cursorX;
|
||||||
this.cursor.y = cursorY;
|
this.cursor.y = cursorY;
|
||||||
|
|
||||||
if (cursorMoved) this.resetCursorBlink();
|
if (cursorMoved) {
|
||||||
|
this.resetCursorBlink();
|
||||||
|
this.emit('cursor-moved');
|
||||||
|
}
|
||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
let attributes = parse2B(str, i);
|
let attributes = parse2B(str, i);
|
||||||
@@ -476,6 +538,7 @@ class TermScreen {
|
|||||||
|
|
||||||
Input.setMouseMode(trackMouseClicks, trackMouseMovement);
|
Input.setMouseMode(trackMouseClicks, trackMouseMovement);
|
||||||
this.selection.selectable = !trackMouseMovement;
|
this.selection.selectable = !trackMouseMovement;
|
||||||
|
$(this.canvas).toggleClass('selectable', !trackMouseMovement);
|
||||||
this.mouseMode = {
|
this.mouseMode = {
|
||||||
clicks: trackMouseClicks,
|
clicks: trackMouseClicks,
|
||||||
movement: trackMouseMovement
|
movement: trackMouseMovement
|
||||||
@@ -545,7 +608,7 @@ class TermScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.scheduleDraw();
|
this.scheduleDraw();
|
||||||
if (this.onload) this.onload()
|
this.emit('load');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Apply labels to buttons and screen title (leading T removed already) */
|
/** Apply labels to buttons and screen title (leading T removed already) */
|
||||||
@@ -622,7 +685,7 @@ class TermScreen {
|
|||||||
const Screen = new TermScreen();
|
const Screen = new TermScreen();
|
||||||
|
|
||||||
let didAddScreen = false;
|
let didAddScreen = false;
|
||||||
Screen.onload = function () {
|
Screen.on('load', () => {
|
||||||
if (didAddScreen) return;
|
if (didAddScreen) return;
|
||||||
didAddScreen = true;
|
didAddScreen = true;
|
||||||
qs('#screen').appendChild(Screen.canvas);
|
qs('#screen').appendChild(Screen.canvas);
|
||||||
@@ -631,4 +694,4 @@ Screen.onload = function () {
|
|||||||
Screen.colors = themes[item.substr(6)]
|
Screen.colors = themes[item.substr(6)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|||||||
@@ -25,27 +25,8 @@ body.term {
|
|||||||
font-size: 20px; // some font heights cause visual glitches with some font renderers. This should be configurable.
|
font-size: 20px; // some font heights cause visual glitches with some font renderers. This should be configurable.
|
||||||
font-family: $screen-stack;
|
font-family: $screen-stack;
|
||||||
|
|
||||||
span {
|
canvas.selectable {
|
||||||
white-space: pre;
|
cursor: text;
|
||||||
}
|
|
||||||
|
|
||||||
> span {
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
> span {
|
|
||||||
position:absolute;
|
|
||||||
left: 0;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.noselect {
|
|
||||||
@include noselect();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user