UNPKG

chrome-devtools-frontend

Version:
236 lines (203 loc) • 6.4 kB
// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. export type PathCommands = Array<string|number>; export interface Quad { p1: Position; p2: Position; p3: Position; p4: Position; } export interface Position { x: number; y: number; } export interface Bounds { minX: number; maxX: number; minY: number; maxY: number; width?: number; height?: number; allPoints: Position[]; } export interface AreaBounds { name: string; bounds: {allPoints: Position[]}; } interface ViewportSize { width: number; height: number; } export interface ResetData { viewportSize: ViewportSize; viewportSizeForMediaQueries?: ViewportSize; deviceScaleFactor: number; pageScaleFactor: number; pageZoomFactor: number; emulationScaleFactor: number; scrollX: number; scrollY: number; } // Overlay class should be used to implement various tools and provide // access to globals via the window object it receives in the constructor. // Old logic is kept temporarily while the tools are being migrated. export class Overlay { protected viewportSize = {width: 800, height: 600}; protected viewportSizeForMediaQueries?: ViewportSize; protected deviceScaleFactor = 1; protected emulationScaleFactor = 1; protected pageScaleFactor = 1; protected pageZoomFactor = 1; protected scrollX = 0; protected scrollY = 0; protected style: CSSStyleSheet[]; protected canvas?: HTMLCanvasElement; protected canvasWidth: number = 0; protected canvasHeight: number = 0; protected platform?: string; // eslint-disable-next-line @typescript-eslint/naming-convention private _window?: Window; // eslint-disable-next-line @typescript-eslint/naming-convention private _document?: Document; // eslint-disable-next-line @typescript-eslint/naming-convention private _context?: CanvasRenderingContext2D|null; // eslint-disable-next-line @typescript-eslint/naming-convention private _installed = false; constructor(window: Window, style: CSSStyleSheet[] = []) { this._window = window; this._document = window.document; if (!Array.isArray(style)) { style = [style]; } this.style = style; } setCanvas(canvas: HTMLCanvasElement) { this.canvas = canvas; this._context = canvas.getContext('2d'); } install() { for (const style of this.style) { adoptStyleSheet(style); } this._installed = true; } uninstall() { for (const style of this.style) { document.adoptedStyleSheets = document.adoptedStyleSheets.filter(s => s !== style); } this._installed = false; } reset(resetData?: ResetData) { if (resetData) { this.viewportSize = resetData.viewportSize; this.viewportSizeForMediaQueries = resetData.viewportSizeForMediaQueries; this.deviceScaleFactor = resetData.deviceScaleFactor; this.pageScaleFactor = resetData.pageScaleFactor; this.pageZoomFactor = resetData.pageZoomFactor; this.emulationScaleFactor = resetData.emulationScaleFactor; this.scrollX = Math.round(resetData.scrollX); this.scrollY = Math.round(resetData.scrollY); } this.resetCanvas(); } resetCanvas() { if (!this.canvas || !this._context) { return; } this.canvas.width = this.deviceScaleFactor * this.viewportSize.width; this.canvas.height = this.deviceScaleFactor * this.viewportSize.height; this.canvas.style.width = this.viewportSize.width + 'px'; this.canvas.style.height = this.viewportSize.height + 'px'; this._context.scale(this.deviceScaleFactor, this.deviceScaleFactor); this.canvasWidth = this.viewportSize.width; this.canvasHeight = this.viewportSize.height; } setPlatform(platform: string) { this.platform = platform; this.document.body.classList.add('platform-' + platform); if (!this._installed) { this.install(); } } dispatch(message: unknown[]) { const functionName = message.shift() as string; // eslint-disable-next-line @typescript-eslint/no-explicit-any (this as any)[functionName].apply(this, message); } eventHasCtrlOrMeta(event: KeyboardEvent) { return this.platform === 'mac' ? (event.metaKey && !event.ctrlKey) : (event.ctrlKey && !event.metaKey); } get context(): CanvasRenderingContext2D { if (!this._context) { throw new Error('Context object is missing'); } return this._context; } get document(): Document { if (!this._document) { throw new Error('Document object is missing'); } return this._document; } get window(): Window { if (!this._window) { throw new Error('Window object is missing'); } return this._window; } get installed(): boolean { return this._installed; } } export function log(text: string) { let element = document.getElementById('log'); if (!element) { element = createChild(document.body, 'div'); element.id = 'log'; } createChild(element, 'div').textContent = text; } export function createChild(parent: HTMLElement, tagName: string, className?: string): HTMLElement { const element = createElement(tagName, className); element.addEventListener('click', function(e: Event) { e.stopPropagation(); }, false); parent.appendChild(element); return element; } export function createTextChild(parent: HTMLElement, text: string): Text { const element = document.createTextNode(text); parent.appendChild(element); return element; } export function createElement(tagName: string, className?: string) { const element = document.createElement(tagName); if (className) { element.className = className; } return element; } export function ellipsify(str: string, maxLength: number) { if (str.length <= maxLength) { return String(str); } return str.substr(0, maxLength - 1) + '\u2026'; } export function constrainNumber(num: number, min: number, max: number): number { if (num < min) { num = min; } else if (num > max) { num = max; } return num; } declare global { // eslint-disable-next-line @typescript-eslint/no-unused-vars interface Document { adoptedStyleSheets: CSSStyleSheet[]; } } export function adoptStyleSheet(styleSheet: CSSStyleSheet) { document.adoptedStyleSheets = [...document.adoptedStyleSheets, styleSheet]; }