UNPKG

chrome-devtools-frontend

Version:
202 lines (177 loc) • 7.33 kB
// Copyright (c) 2020 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. /* eslint-disable rulesdir/no-lit-render-outside-of-view */ import '../../../ui/components/icon_button/icon_button.js'; import * as i18n from '../../../core/i18n/i18n.js'; import * as Buttons from '../../../ui/components/buttons/buttons.js'; import * as Lit from '../../../ui/lit/lit.js'; import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js'; import linearMemoryNavigatorStyles from './linearMemoryNavigator.css.js'; const UIStrings = { /** *@description Tooltip text that appears when hovering over a valid memory address (e.g. 0x0) in the address line in the Linear memory inspector. */ enterAddress: 'Enter address', /** *@description Tooltip text that appears when hovering over the button to go back in history in the Linear Memory Navigator */ goBackInAddressHistory: 'Go back in address history', /** *@description Tooltip text that appears when hovering over the button to go forward in history in the Linear Memory Navigator */ goForwardInAddressHistory: 'Go forward in address history', /** *@description Tooltip text that appears when hovering over the page back icon in the Linear Memory Navigator */ previousPage: 'Previous page', /** *@description Tooltip text that appears when hovering over the next page icon in the Linear Memory Navigator */ nextPage: 'Next page', /** *@description Text to refresh the page */ refresh: 'Refresh', } as const; const str_ = i18n.i18n.registerUIStrings('panels/linear_memory_inspector/components/LinearMemoryNavigator.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); const {render, html, Directives: {ifDefined}} = Lit; export const enum Navigation { BACKWARD = 'Backward', FORWARD = 'Forward', } export class AddressInputChangedEvent extends Event { static readonly eventName = 'addressinputchanged'; data: {address: string, mode: Mode}; constructor(address: string, mode: Mode) { super(AddressInputChangedEvent.eventName); this.data = {address, mode}; } } export class PageNavigationEvent extends Event { static readonly eventName = 'pagenavigation'; data: Navigation; constructor(navigation: Navigation) { super(PageNavigationEvent.eventName, {}); this.data = navigation; } } export class HistoryNavigationEvent extends Event { static readonly eventName = 'historynavigation'; data: Navigation; constructor(navigation: Navigation) { super(HistoryNavigationEvent.eventName, {}); this.data = navigation; } } export class RefreshRequestedEvent extends Event { static readonly eventName = 'refreshrequested'; constructor() { super(RefreshRequestedEvent.eventName, {}); } } export interface LinearMemoryNavigatorData { address: string; mode: Mode; canGoBackInHistory: boolean; canGoForwardInHistory: boolean; valid: boolean; error: string|undefined; } export const enum Mode { EDIT = 'Edit', SUBMITTED = 'Submitted', INVALID_SUBMIT = 'InvalidSubmit', } export class LinearMemoryNavigator extends HTMLElement { readonly #shadow = this.attachShadow({mode: 'open'}); #address = '0'; #error: string|undefined = undefined; #valid = true; #canGoBackInHistory = false; #canGoForwardInHistory = false; set data(data: LinearMemoryNavigatorData) { this.#address = data.address; this.#error = data.error; this.#valid = data.valid; this.#canGoBackInHistory = data.canGoBackInHistory; this.#canGoForwardInHistory = data.canGoForwardInHistory; this.#render(); const addressInput = this.#shadow.querySelector<HTMLInputElement>('.address-input'); if (addressInput) { if (data.mode === Mode.SUBMITTED) { addressInput.blur(); } else if (data.mode === Mode.INVALID_SUBMIT) { addressInput.select(); } } } #render(): void { // Disabled until https://crbug.com/1079231 is fixed. // clang-format off const result = html` <style>${linearMemoryNavigatorStyles}</style> <div class="navigator"> <div class="navigator-item"> ${this.#createButton({icon: 'undo', title: i18nString(UIStrings.goBackInAddressHistory), event: new HistoryNavigationEvent(Navigation.BACKWARD), enabled: this.#canGoBackInHistory, jslogContext:'linear-memory-inspector.history-back'})} ${this.#createButton({icon: 'redo', title: i18nString(UIStrings.goForwardInAddressHistory), event: new HistoryNavigationEvent(Navigation.FORWARD), enabled: this.#canGoForwardInHistory, jslogContext:'linear-memory-inspector.history-forward'})} </div> <div class="navigator-item"> ${this.#createButton({icon: 'chevron-left', title: i18nString(UIStrings.previousPage), event: new PageNavigationEvent(Navigation.BACKWARD), enabled: true, jslogContext:'linear-memory-inspector.previous-page'})} ${this.#createAddressInput()} ${this.#createButton({icon: 'chevron-right', title: i18nString(UIStrings.nextPage), event: new PageNavigationEvent(Navigation.FORWARD), enabled: true, jslogContext:'linear-memory-inspector.next-page'})} </div> ${this.#createButton({icon: 'refresh', title: i18nString(UIStrings.refresh), event: new RefreshRequestedEvent(), enabled: true, jslogContext:'linear-memory-inspector.refresh'})} </div> `; render(result, this.#shadow, {host: this}); // clang-format on } #createAddressInput(): Lit.TemplateResult { const classMap = { 'address-input': true, invalid: !this.#valid, }; return html` <input class=${Lit.Directives.classMap(classMap)} data-input="true" .value=${this.#address} jslog=${VisualLogging.textField('linear-memory-inspector.address').track({ change: true, })} title=${ifDefined(this.#valid ? i18nString(UIStrings.enterAddress) : this.#error)} @change=${ this.#onAddressChange.bind(this, Mode.SUBMITTED)} @input=${this.#onAddressChange.bind(this, Mode.EDIT)}/>`; } #onAddressChange(mode: Mode, event: Event): void { const addressInput = event.target as HTMLInputElement; this.dispatchEvent(new AddressInputChangedEvent(addressInput.value, mode)); } #createButton(data: {icon: string, title: string, event: Event, enabled: boolean, jslogContext: string}): Lit.TemplateResult { return html` <devtools-button class="navigator-button" .data=${ {variant: Buttons.Button.Variant.ICON, iconName: data.icon, disabled: !data.enabled} as Buttons.Button.ButtonData} jslog=${VisualLogging.action().track({click: true, keydown: 'Enter'}).context(data.jslogContext)} data-button=${data.event.type} title=${data.title} @click=${this.dispatchEvent.bind(this, data.event)} ></devtools-button>`; } } customElements.define('devtools-linear-memory-inspector-navigator', LinearMemoryNavigator); declare global { interface HTMLElementTagNameMap { 'devtools-linear-memory-inspector-navigator': LinearMemoryNavigator; } }