Support arrow-keys
Change-Id: I4cfd99001ea99888c8781e018f67c644d1d6e3d1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/403597
Reviewed-by: Florin Malita <fmalita@chromium.org>
diff --git a/modules/canvaskit/npm_build/extra.html b/modules/canvaskit/npm_build/extra.html
index 834dbd0..ef5e1e5 100644
--- a/modules/canvaskit/npm_build/extra.html
+++ b/modules/canvaskit/npm_build/extra.html
@@ -32,7 +32,7 @@
<h2> Paragraph </h2>
<canvas id=para1 width=600 height=600></canvas>
-<canvas id=para2 width=600 height=600></canvas>
+<canvas id=para2 width=600 height=600 tabindex='-1'></canvas>
<h2> CanvasKit can serialize/deserialize .skp files</h2>
<canvas id=skp width=500 height=500></canvas>
@@ -395,7 +395,7 @@
function mid(a, b) { return (a + b) * 0.5; }
- function runs_pos_to_index(runs, x, y) {
+ function runs_x_to_index(runs, x) {
for (const r of runs) {
for (let i = 1; i < r.offsets.length; i += 1) {
if (x < r.positions[i*2]) {
@@ -417,7 +417,7 @@
}
for (const l of lines) {
if (y <= l.bottom) {
- return runs_pos_to_index(l.runs, x, y);
+ return runs_x_to_index(l.runs, x);
}
}
return text.length;
@@ -439,15 +439,22 @@
return r.positions[i*2];
}
}
+ return null;
+ }
+
+ function lines_index_to_line_index(lines, index) {
+ let i = 0;
+ for (const l of lines) {
+ if (index <= l.textRange.last) {
+ return i;
+ }
+ i += 1;
+ }
+ return lines.length-1;
}
function lines_index_to_line(lines, index) {
- for (const l of lines) {
- if (index <= l.textRange.last) {
- return l;
- }
- }
- return lines[lines.length-1];
+ return lines[lines_index_to_line_index(lines, index)];
}
function lines_index_to_x(lines, index) {
@@ -481,7 +488,58 @@
return path;
}
- let INDEX = 0;
+ let editor = {
+ _text: null,
+ _lines: null,
+ _cursor: null,
+ _width: 1e20,
+ _index: { start: 0, end: 0 },
+
+ init: function(text, lines, cursor, width) {
+ this._text = text;
+ this._lines = lines;
+ this._cursor = cursor;
+ this._width = width;
+ },
+ setIndex: function(i) {
+ this._index.start = this._index.end = i;
+ const l = lines_index_to_line(this._lines, i);
+ const x = runs_index_to_x(l.runs, i);
+ this._cursor.place(x, l.top, l.bottom);
+ },
+ setIndices: function(a, b) {
+ if (a > b) { [a, b] = [b, a]; }
+ this._index.start = a;
+ this._index.end = b;
+ this._cursor.setPath(lines_indices_to_path(this._lines, a, b, fm, this._width));
+ },
+ moveDX: function(dx) {
+ let index;
+ if (this._index.start == this._index.end) {
+ // just adjust and pin
+ index = Math.max(Math.min(this._index.start + dx, this._text.length), 0);
+ } else {
+ // 'deselect' the region, and turn it into just a single index
+ index = dx < 0 ? this._index.start : this._index.end;
+ }
+ this.setIndex(index);
+ },
+ moveDY: function(dy) {
+ let index = (dy < 0) ? this._index.start : this._index.end;
+ const i = lines_index_to_line_index(this._lines, index);
+ if (dy < 0 && i == 0) {
+ index = 0;
+ } else if (dy > 0 && i == this._lines.length - 1) {
+ index = this._text.length;
+ } else {
+ const x = runs_index_to_x(this._lines[i].runs, index);
+ // todo: statefully track "original" x when an up/down sequence started,
+ // so we can avoid drift.
+ index = runs_x_to_index(this._lines[i+dy].runs, x);
+ }
+ this.setIndex(index);
+ },
+ };
let lines;
function drawFrame(canvas) {
@@ -489,6 +547,7 @@
canvas.drawParagraph(paragraph, 0, 0);
if (!lines) {
lines = paragraph.getShapedLines();
+ editor.init(text, lines, cursor, WIDTH);
}
if (mouse.isActive()) {
@@ -496,12 +555,9 @@
const a = lines_pos_to_index(lines, pos[0], pos[1]);
const b = lines_pos_to_index(lines, pos[2], pos[3]);
if (a == b) {
- INDEX = a;
- const l = lines_index_to_line(lines, INDEX);
- const x = runs_index_to_x(l.runs, INDEX);
- cursor.place(x, l.top, l.bottom);
+ editor.setIndex(a);
} else {
- cursor.setPath(lines_indices_to_path(lines, a, b, fm, WIDTH));
+ editor.setIndices(a, b);
}
}
@@ -537,9 +593,25 @@
}
};
+ function keyhandler(e) {
+ switch (e.key) {
+ case 'ArrowLeft': editor.moveDX(-1); break;
+ case 'ArrowRight': editor.moveDX(1); break;
+ case 'ArrowUp':
+ e.preventDefault();
+ editor.moveDY(-1);
+ break;
+ case 'ArrowDown':
+ e.preventDefault();
+ editor.moveDY(1);
+ break;
+ }
+ }
+
document.getElementById('para2').addEventListener('pointermove', interact);
document.getElementById('para2').addEventListener('pointerdown', interact);
document.getElementById('para2').addEventListener('pointerup', interact);
+ document.getElementById('para2').addEventListener('keydown', keyhandler);
return surface;
}