UNPKG

7.57 kBPlain TextView Raw
1// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Copyright (C) 2012 Google Inc. All rights reserved.
6
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions
9// are met:
10
11// 1. Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13// 2. Redistributions in binary form must reproduce the above copyright
14// notice, this list of conditions and the following disclaimer in the
15// documentation and/or other materials provided with the distribution.
16// 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
17// its contributors may be used to endorse or promote products derived
18// from this software without specific prior written permission.
19
20// THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
21// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23// DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
24// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31import type {ResetData} from './common.js';
32import {Overlay} from './common.js';
33import type {Delegate} from './drag_resize_handler.js';
34import {DragResizeHandler, ResizerType} from './drag_resize_handler.js';
35import type {ContainerQueryHighlight} from './highlight_container_query.js';
36import {drawContainerQueryHighlight} from './highlight_container_query.js';
37import type {FlexContainerHighlight} from './highlight_flex_common.js';
38import {drawLayoutFlexContainerHighlight} from './highlight_flex_common.js';
39import type {GridHighlight} from './highlight_grid_common.js';
40import {drawLayoutGridHighlight} from './highlight_grid_common.js';
41import type {IsolatedElementHighlight} from './highlight_isolated_element.js';
42import {drawIsolatedElementHighlight} from './highlight_isolated_element.js';
43import type {ScrollSnapHighlight} from './highlight_scroll_snap.js';
44import {drawScrollSnapHighlight} from './highlight_scroll_snap.js';
45
46export type PersistentToolMessage = {
47 highlightType: string,
48 highlightIndex: number,
49 newWidth: string,
50 newHeight: string,
51 resizerType: ResizerType,
52};
53
54interface DraggableMetadata {
55 type: ResizerType;
56 highlightIndex: number;
57 initialWidth?: number;
58 initialHeight?: number;
59}
60
61function makeDraggableDelegate(overlay: PersistentOverlay): Delegate {
62 return {
63 getDraggable: (x, y) => {
64 const result = overlay.isPointInDraggablePath(x, y);
65 if (!result) {
66 return;
67 }
68
69 return {
70 type: result.type,
71 initialWidth: result.initialWidth,
72 initialHeight: result.initialHeight,
73 id: result.highlightIndex,
74 update: ({width, height}: {width?: number, height?: number}) => {
75 window.InspectorOverlayHost.send({
76 highlightType: 'isolatedElement',
77 highlightIndex: result.highlightIndex,
78 newWidth: `${width}px`,
79 newHeight: `${height}px`,
80 resizerType: result.type,
81 });
82 },
83 };
84 },
85 };
86}
87
88export class PersistentOverlay extends Overlay {
89 private gridLabelState = {gridLayerCounter: 0};
90
91 private gridLabels!: HTMLElement;
92 private draggableBorders: Map<number, {
93 widthPath: Path2D,
94 heightPath: Path2D,
95 bidirectionPath: Path2D,
96 highlightIndex: number,
97 initialWidth: number,
98 initialHeight: number,
99 }> = new Map();
100 private dragHandler?: DragResizeHandler;
101
102 reset(data: ResetData) {
103 super.reset(data);
104 this.gridLabelState.gridLayerCounter = 0;
105 this.gridLabels.innerHTML = '';
106 }
107
108 renderGridMarkup() {
109 const gridLabels = this.document.createElement('div');
110 gridLabels.id = 'grid-label-container';
111 this.document.body.append(gridLabels);
112 this.gridLabels = gridLabels;
113 }
114
115 install() {
116 this.document.body.classList.add('fill');
117
118 const canvas = this.document.createElement('canvas');
119 canvas.id = 'canvas';
120 canvas.classList.add('fill');
121 this.document.body.append(canvas);
122
123 this.renderGridMarkup();
124
125 this.setCanvas(canvas);
126
127 super.install();
128 this.dragHandler?.install();
129 }
130
131 uninstall() {
132 this.document.body.classList.remove('fill');
133 this.document.body.innerHTML = '';
134 this.draggableBorders = new Map();
135 super.uninstall();
136 this.dragHandler?.uninstall();
137 }
138
139 drawGridHighlight(highlight: GridHighlight) {
140 this.context.save();
141 drawLayoutGridHighlight(
142 highlight, this.context, this.deviceScaleFactor, this.canvasWidth, this.canvasHeight, this.emulationScaleFactor,
143 this.gridLabelState);
144 this.context.restore();
145 }
146
147 drawFlexContainerHighlight(highlight: FlexContainerHighlight) {
148 this.context.save();
149 drawLayoutFlexContainerHighlight(
150 highlight, this.context, this.deviceScaleFactor, this.canvasWidth, this.canvasHeight,
151 this.emulationScaleFactor);
152 this.context.restore();
153 }
154
155 drawScrollSnapHighlight(highlight: ScrollSnapHighlight) {
156 this.context.save();
157 drawScrollSnapHighlight(highlight, this.context, this.emulationScaleFactor);
158 this.context.restore();
159 }
160
161 drawContainerQueryHighlight(highlight: ContainerQueryHighlight) {
162 this.context.save();
163 drawContainerQueryHighlight(highlight, this.context, this.emulationScaleFactor);
164 this.context.restore();
165 }
166
167 drawIsolatedElementHighlight(highlight: IsolatedElementHighlight) {
168 if (!this.dragHandler) {
169 this.dragHandler = new DragResizeHandler(this.document, makeDraggableDelegate(this));
170 this.dragHandler.install();
171 }
172
173 this.context.save();
174 const {widthPath, heightPath, bidirectionPath, currentWidth, currentHeight, highlightIndex} =
175 drawIsolatedElementHighlight(
176 highlight, this.context, this.canvasWidth, this.canvasHeight, this.emulationScaleFactor);
177
178 this.draggableBorders.set(highlightIndex, {
179 widthPath,
180 heightPath,
181 bidirectionPath,
182 highlightIndex,
183 initialWidth: currentWidth,
184 initialHeight: currentHeight,
185 });
186 this.context.restore();
187 }
188
189 isPointInDraggablePath(x: number, y: number): DraggableMetadata|undefined {
190 for (const {widthPath, heightPath, bidirectionPath, highlightIndex, initialWidth, initialHeight} of this
191 .draggableBorders.values()) {
192 if (this.context.isPointInPath(widthPath, x, y)) {
193 return {
194 type: ResizerType.WIDTH,
195 highlightIndex,
196 initialWidth,
197 };
198 }
199 if (this.context.isPointInPath(heightPath, x, y)) {
200 return {
201 type: ResizerType.HEIGHT,
202 highlightIndex,
203 initialHeight,
204 };
205 }
206 if (this.context.isPointInPath(bidirectionPath, x, y)) {
207 return {
208 type: ResizerType.BIDIRECTION,
209 highlightIndex,
210 initialWidth,
211 initialHeight,
212 };
213 }
214 }
215
216 return;
217 }
218}