1 |
|
2 |
|
3 |
|
4 |
|
5 | import {Overlay} from './common.js';
|
6 |
|
7 | export type ScreenshotToolMessage = {
|
8 | x: number,
|
9 | y: number,
|
10 | width: number,
|
11 | height: number,
|
12 | };
|
13 |
|
14 | let anchor: {x: number, y: number}|null = null;
|
15 | let position: {x: number, y: number}|null = null;
|
16 |
|
17 | export class ScreenshotOverlay extends Overlay {
|
18 | private zone!: HTMLElement;
|
19 |
|
20 | constructor(window: Window, style: CSSStyleSheet[] = []) {
|
21 | super(window, style);
|
22 | this.onMouseDown = this.onMouseDown.bind(this);
|
23 | this.onMouseUp = this.onMouseUp.bind(this);
|
24 | this.onMouseMove = this.onMouseMove.bind(this);
|
25 | this.onKeyDown = this.onKeyDown.bind(this);
|
26 | }
|
27 |
|
28 | install() {
|
29 | const root = this.document.documentElement;
|
30 | root.addEventListener('mousedown', this.onMouseDown, true);
|
31 | root.addEventListener('mouseup', this.onMouseUp, true);
|
32 | root.addEventListener('mousemove', this.onMouseMove, true);
|
33 | root.addEventListener('keydown', this.onKeyDown, true);
|
34 |
|
35 | const zone = this.document.createElement('div');
|
36 | zone.id = 'zone';
|
37 | this.document.body.append(zone);
|
38 |
|
39 | this.zone = zone;
|
40 |
|
41 | super.install();
|
42 | }
|
43 |
|
44 | uninstall() {
|
45 | this.document.body.innerHTML = '';
|
46 | const root = this.document.documentElement;
|
47 | root.removeEventListener('mousedown', this.onMouseDown, true);
|
48 | root.removeEventListener('mouseup', this.onMouseUp, true);
|
49 | root.removeEventListener('mousemove', this.onMouseMove, true);
|
50 | root.removeEventListener('keydown', this.onKeyDown, true);
|
51 | super.uninstall();
|
52 | }
|
53 |
|
54 | onMouseDown(event: MouseEvent) {
|
55 | anchor = {x: event.pageX, y: event.pageY};
|
56 | position = anchor;
|
57 | this.updateZone();
|
58 | event.stopPropagation();
|
59 | event.preventDefault();
|
60 | }
|
61 |
|
62 | onMouseUp(event: MouseEvent) {
|
63 | if (anchor && position) {
|
64 | const rect = currentRect();
|
65 | if (rect.width >= 5 && rect.height >= 5) {
|
66 | this.window.InspectorOverlayHost.send(rect);
|
67 | }
|
68 | }
|
69 | cancel();
|
70 | this.updateZone();
|
71 | event.stopPropagation();
|
72 | event.preventDefault();
|
73 | }
|
74 |
|
75 | onMouseMove(event: MouseEvent) {
|
76 | if (anchor && event.buttons === 1) {
|
77 | position = {x: event.pageX, y: event.pageY};
|
78 | } else {
|
79 | anchor = null;
|
80 | }
|
81 | this.updateZone();
|
82 | event.stopPropagation();
|
83 | event.preventDefault();
|
84 | }
|
85 |
|
86 | onKeyDown(event: KeyboardEvent) {
|
87 | if (anchor && event.key === 'Escape') {
|
88 | cancel();
|
89 | this.updateZone();
|
90 | event.stopPropagation();
|
91 | event.preventDefault();
|
92 | }
|
93 | }
|
94 |
|
95 | updateZone() {
|
96 | const zone = this.zone;
|
97 | if (!position || !anchor) {
|
98 | zone.style.display = 'none';
|
99 | return;
|
100 | }
|
101 | zone.style.display = 'block';
|
102 | const rect = currentRect();
|
103 | zone.style.left = rect.x + 'px';
|
104 | zone.style.top = rect.y + 'px';
|
105 | zone.style.width = rect.width + 'px';
|
106 | zone.style.height = rect.height + 'px';
|
107 | }
|
108 | }
|
109 |
|
110 | function currentRect() {
|
111 | if (!anchor) {
|
112 | throw new Error('Error calculating currentRect: no anchor was defined.');
|
113 | }
|
114 | if (!position) {
|
115 | throw new Error('Error calculating currentRect: no position was defined.');
|
116 | }
|
117 | return {
|
118 | x: Math.min(anchor.x, position.x),
|
119 | y: Math.min(anchor.y, position.y),
|
120 | width: Math.abs(anchor.x - position.x),
|
121 | height: Math.abs(anchor.y - position.y),
|
122 | };
|
123 | }
|
124 |
|
125 | function cancel() {
|
126 | anchor = null;
|
127 | position = null;
|
128 | }
|