debug-server-next
Version:
Dev server for hippy-core.
416 lines (415 loc) • 18.5 kB
JavaScript
// Copyright (c) 2015 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_underscored_properties */
import * as Common from '../../core/common/common.js';
import * as Host from '../../core/host/host.js';
import * as i18n from '../../core/i18n/i18n.js';
import * as Root from '../../core/root/root.js';
import * as Bindings from '../../models/bindings/bindings.js';
import * as ColorPicker from '../../ui/legacy/components/color_picker/color_picker.js';
import * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';
import * as UI from '../../ui/legacy/legacy.js';
const UIStrings = {
/**
* @description Tooltip text for an icon that opens the cubic bezier editor, which is a tool that
* allows the user to edit cubic-bezier CSS properties directly.
*/
openCubicBezierEditor: 'Open cubic bezier editor',
/**
* @description Tooltip text for an icon that opens shadow editor. The shadow editor is a tool
* which allows the user to edit CSS shadow properties.
*/
openShadowEditor: 'Open shadow editor',
};
const str_ = i18n.i18n.registerUIStrings('panels/elements/ColorSwatchPopoverIcon.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
export class BezierPopoverIcon {
_treeElement;
_swatchPopoverHelper;
_swatch;
_boundBezierChanged;
_boundOnScroll;
_bezierEditor;
_scrollerElement;
_originalPropertyText;
constructor(treeElement, swatchPopoverHelper, swatch) {
this._treeElement = treeElement;
this._swatchPopoverHelper = swatchPopoverHelper;
this._swatch = swatch;
UI.Tooltip.Tooltip.install(this._swatch.iconElement(), i18nString(UIStrings.openCubicBezierEditor));
this._swatch.iconElement().addEventListener('click', this._iconClick.bind(this), false);
this._swatch.iconElement().addEventListener('mousedown', (event) => event.consume(), false);
this._boundBezierChanged = this._bezierChanged.bind(this);
this._boundOnScroll = this._onScroll.bind(this);
}
_iconClick(event) {
if (Root.Runtime.experiments.isEnabled('fontEditor')) {
Host.userMetrics.cssEditorOpened('bezierEditor');
}
event.consume(true);
if (this._swatchPopoverHelper.isShowing()) {
this._swatchPopoverHelper.hide(true);
return;
}
const cubicBezier = UI.Geometry.CubicBezier.parse(this._swatch.bezierText()) ||
UI.Geometry.CubicBezier.parse('linear');
this._bezierEditor = new InlineEditor.BezierEditor.BezierEditor(cubicBezier);
this._bezierEditor.setBezier(cubicBezier);
this._bezierEditor.addEventListener(InlineEditor.BezierEditor.Events.BezierChanged, this._boundBezierChanged);
this._swatchPopoverHelper.show(this._bezierEditor, this._swatch.iconElement(), this._onPopoverHidden.bind(this));
this._scrollerElement = this._swatch.enclosingNodeOrSelfWithClass('style-panes-wrapper');
if (this._scrollerElement) {
this._scrollerElement.addEventListener('scroll', this._boundOnScroll, false);
}
this._originalPropertyText = this._treeElement.property.propertyText;
this._treeElement.parentPane().setEditingStyle(true);
const uiLocation = Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance().propertyUILocation(this._treeElement.property, false /* forName */);
if (uiLocation) {
Common.Revealer.reveal(uiLocation, true /* omitFocus */);
}
}
_bezierChanged(event) {
this._swatch.setBezierText(event.data);
this._treeElement.applyStyleText(this._treeElement.renderedPropertyText(), false);
}
_onScroll(_event) {
this._swatchPopoverHelper.hide(true);
}
_onPopoverHidden(commitEdit) {
if (this._scrollerElement) {
this._scrollerElement.removeEventListener('scroll', this._boundOnScroll, false);
}
if (this._bezierEditor) {
this._bezierEditor.removeEventListener(InlineEditor.BezierEditor.Events.BezierChanged, this._boundBezierChanged);
}
this._bezierEditor = undefined;
const propertyText = commitEdit ? this._treeElement.renderedPropertyText() : this._originalPropertyText || '';
this._treeElement.applyStyleText(propertyText, true);
this._treeElement.parentPane().setEditingStyle(false);
delete this._originalPropertyText;
}
}
export class ColorSwatchPopoverIcon {
_treeElement;
_swatchPopoverHelper;
_swatch;
_contrastInfo;
_boundSpectrumChanged;
_boundOnScroll;
_spectrum;
_scrollerElement;
_originalPropertyText;
constructor(treeElement, swatchPopoverHelper, swatch) {
this._treeElement = treeElement;
this._swatchPopoverHelper = swatchPopoverHelper;
this._swatch = swatch;
this._swatch.addEventListener('swatch-click', this._iconClick.bind(this));
this._contrastInfo = null;
this._boundSpectrumChanged = this._spectrumChanged.bind(this);
this._boundOnScroll = this._onScroll.bind(this);
}
_generateCSSVariablesPalette() {
const matchedStyles = this._treeElement.matchedStyles();
const style = this._treeElement.property.ownerStyle;
const cssVariables = matchedStyles.availableCSSVariables(style);
const colors = [];
const colorNames = [];
for (const cssVariable of cssVariables) {
if (cssVariable === this._treeElement.property.name) {
continue;
}
const value = matchedStyles.computeCSSVariable(style, cssVariable);
if (!value) {
continue;
}
const color = Common.Color.Color.parse(value);
if (!color) {
continue;
}
colors.push(value);
colorNames.push(cssVariable);
}
return { title: 'CSS Variables', mutable: false, matchUserFormat: true, colors: colors, colorNames: colorNames };
}
setContrastInfo(contrastInfo) {
this._contrastInfo = contrastInfo;
}
_iconClick(event) {
if (Root.Runtime.experiments.isEnabled('fontEditor')) {
Host.userMetrics.cssEditorOpened('colorPicker');
}
event.consume(true);
this.showPopover();
}
showPopover() {
if (this._swatchPopoverHelper.isShowing()) {
this._swatchPopoverHelper.hide(true);
return;
}
const color = this._swatch.getColor();
let format = this._swatch.getFormat();
if (!color || !format) {
return;
}
if (format === Common.Color.Format.Original) {
format = color.format();
}
this._spectrum = new ColorPicker.Spectrum.Spectrum(this._contrastInfo);
this._spectrum.setColor(color, format);
this._spectrum.addPalette(this._generateCSSVariablesPalette());
this._spectrum.addEventListener(ColorPicker.Spectrum.Events.SizeChanged, this._spectrumResized, this);
this._spectrum.addEventListener(ColorPicker.Spectrum.Events.ColorChanged, this._boundSpectrumChanged);
this._swatchPopoverHelper.show(this._spectrum, this._swatch, this._onPopoverHidden.bind(this));
this._scrollerElement = this._swatch.enclosingNodeOrSelfWithClass('style-panes-wrapper');
if (this._scrollerElement) {
this._scrollerElement.addEventListener('scroll', this._boundOnScroll, false);
}
this._originalPropertyText = this._treeElement.property.propertyText;
this._treeElement.parentPane().setEditingStyle(true);
const uiLocation = Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance().propertyUILocation(this._treeElement.property, false /* forName */);
if (uiLocation) {
Common.Revealer.reveal(uiLocation, true /* omitFocus */);
}
}
_spectrumResized(_event) {
this._swatchPopoverHelper.reposition();
}
_spectrumChanged(event) {
const color = Common.Color.Color.parse(event.data);
if (!color) {
return;
}
const colorName = this._spectrum ? this._spectrum.colorName() : undefined;
const text = colorName && colorName.startsWith('--') ? `var(${colorName})` : color.asString();
this._swatch.renderColor(color);
const value = this._swatch.firstElementChild;
if (value) {
value.remove();
this._swatch.createChild('span').textContent = text;
}
this._treeElement.applyStyleText(this._treeElement.renderedPropertyText(), false);
}
_onScroll(_event) {
this._swatchPopoverHelper.hide(true);
}
_onPopoverHidden(commitEdit) {
if (this._scrollerElement) {
this._scrollerElement.removeEventListener('scroll', this._boundOnScroll, false);
}
if (this._spectrum) {
this._spectrum.removeEventListener(ColorPicker.Spectrum.Events.ColorChanged, this._boundSpectrumChanged);
}
this._spectrum = undefined;
const propertyText = commitEdit ? this._treeElement.renderedPropertyText() : this._originalPropertyText || '';
this._treeElement.applyStyleText(propertyText, true);
this._treeElement.parentPane().setEditingStyle(false);
delete this._originalPropertyText;
}
}
export class ShadowSwatchPopoverHelper {
_treeElement;
_swatchPopoverHelper;
_shadowSwatch;
_iconElement;
_boundShadowChanged;
_boundOnScroll;
_cssShadowEditor;
_scrollerElement;
_originalPropertyText;
constructor(treeElement, swatchPopoverHelper, shadowSwatch) {
this._treeElement = treeElement;
this._swatchPopoverHelper = swatchPopoverHelper;
this._shadowSwatch = shadowSwatch;
this._iconElement = shadowSwatch.iconElement();
UI.Tooltip.Tooltip.install(this._iconElement, i18nString(UIStrings.openShadowEditor));
this._iconElement.addEventListener('click', this._iconClick.bind(this), false);
this._iconElement.addEventListener('mousedown', event => event.consume(), false);
this._boundShadowChanged = this._shadowChanged.bind(this);
this._boundOnScroll = this._onScroll.bind(this);
}
_iconClick(event) {
if (Root.Runtime.experiments.isEnabled('fontEditor')) {
Host.userMetrics.cssEditorOpened('shadowEditor');
}
event.consume(true);
this.showPopover();
}
showPopover() {
if (this._swatchPopoverHelper.isShowing()) {
this._swatchPopoverHelper.hide(true);
return;
}
this._cssShadowEditor = new InlineEditor.CSSShadowEditor.CSSShadowEditor();
this._cssShadowEditor.setModel(this._shadowSwatch.model());
this._cssShadowEditor.addEventListener(InlineEditor.CSSShadowEditor.Events.ShadowChanged, this._boundShadowChanged);
this._swatchPopoverHelper.show(this._cssShadowEditor, this._iconElement, this._onPopoverHidden.bind(this));
this._scrollerElement = this._iconElement.enclosingNodeOrSelfWithClass('style-panes-wrapper');
if (this._scrollerElement) {
this._scrollerElement.addEventListener('scroll', this._boundOnScroll, false);
}
this._originalPropertyText = this._treeElement.property.propertyText;
this._treeElement.parentPane().setEditingStyle(true);
const uiLocation = Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance().propertyUILocation(this._treeElement.property, false /* forName */);
if (uiLocation) {
Common.Revealer.reveal(uiLocation, true /* omitFocus */);
}
}
_shadowChanged(event) {
this._shadowSwatch.setCSSShadow(event.data);
this._treeElement.applyStyleText(this._treeElement.renderedPropertyText(), false);
}
_onScroll(_event) {
this._swatchPopoverHelper.hide(true);
}
_onPopoverHidden(commitEdit) {
if (this._scrollerElement) {
this._scrollerElement.removeEventListener('scroll', this._boundOnScroll, false);
}
if (this._cssShadowEditor) {
this._cssShadowEditor.removeEventListener(InlineEditor.CSSShadowEditor.Events.ShadowChanged, this._boundShadowChanged);
}
this._cssShadowEditor = undefined;
const propertyText = commitEdit ? this._treeElement.renderedPropertyText() : this._originalPropertyText || '';
this._treeElement.applyStyleText(propertyText, true);
this._treeElement.parentPane().setEditingStyle(false);
delete this._originalPropertyText;
}
}
export class FontEditorSectionManager {
_treeElementMap;
_swatchPopoverHelper;
_section;
_parentPane;
_fontEditor;
_scrollerElement;
_boundFontChanged;
_boundOnScroll;
_boundResized;
constructor(swatchPopoverHelper, section) {
this._treeElementMap = new Map();
this._swatchPopoverHelper = swatchPopoverHelper;
this._section = section;
this._parentPane = null;
this._fontEditor = null;
this._scrollerElement = null;
this._boundFontChanged = this._fontChanged.bind(this);
this._boundOnScroll = this._onScroll.bind(this);
this._boundResized = this._fontEditorResized.bind(this);
}
_fontChanged(event) {
const { propertyName, value } = event.data;
const treeElement = this._treeElementMap.get(propertyName);
this._updateFontProperty(propertyName, value, treeElement);
}
async _updateFontProperty(propertyName, value, treeElement) {
if (treeElement && treeElement.treeOutline && treeElement.valueElement && treeElement.property.parsedOk &&
treeElement.property.range) {
let elementRemoved = false;
treeElement.valueElement.textContent = value;
treeElement.property.value = value;
let styleText;
const propertyName = treeElement.property.name;
if (value.length) {
styleText = treeElement.renderedPropertyText();
}
else {
styleText = '';
elementRemoved = true;
this._fixIndex(treeElement.property.index);
}
this._treeElementMap.set(propertyName, treeElement);
await treeElement.applyStyleText(styleText, true);
if (elementRemoved) {
this._treeElementMap.delete(propertyName);
}
}
else if (value.length) {
const newProperty = this._section.addNewBlankProperty();
if (newProperty) {
newProperty.property.name = propertyName;
newProperty.property.value = value;
newProperty.updateTitle();
await newProperty.applyStyleText(newProperty.renderedPropertyText(), true);
this._treeElementMap.set(newProperty.property.name, newProperty);
}
}
this._section.onpopulate();
this._swatchPopoverHelper.reposition();
return;
}
_fontEditorResized() {
this._swatchPopoverHelper.reposition();
}
_fixIndex(removedIndex) {
for (const treeElement of this._treeElementMap.values()) {
if (treeElement.property.index > removedIndex) {
treeElement.property.index -= 1;
}
}
}
_createPropertyValueMap() {
const propertyMap = new Map();
for (const fontProperty of this._treeElementMap) {
const propertyName = fontProperty[0];
const treeElement = fontProperty[1];
if (treeElement.property.value.length) {
propertyMap.set(propertyName, treeElement.property.value);
}
else {
this._treeElementMap.delete(propertyName);
}
}
return propertyMap;
}
registerFontProperty(treeElement) {
const propertyName = treeElement.property.name;
if (this._treeElementMap.has(propertyName)) {
const treeElementFromMap = this._treeElementMap.get(propertyName);
if (!treeElement.overloaded() || (treeElementFromMap && treeElementFromMap.overloaded())) {
this._treeElementMap.set(propertyName, treeElement);
}
}
else {
this._treeElementMap.set(propertyName, treeElement);
}
}
async showPopover(iconElement, parentPane) {
if (this._swatchPopoverHelper.isShowing()) {
this._swatchPopoverHelper.hide(true);
return;
}
this._parentPane = parentPane;
const propertyValueMap = this._createPropertyValueMap();
this._fontEditor = new InlineEditor.FontEditor.FontEditor(propertyValueMap);
this._fontEditor.addEventListener(InlineEditor.FontEditor.Events.FontChanged, this._boundFontChanged);
this._fontEditor.addEventListener(InlineEditor.FontEditor.Events.FontEditorResized, this._boundResized);
this._swatchPopoverHelper.show(this._fontEditor, iconElement, this._onPopoverHidden.bind(this));
this._scrollerElement = iconElement.enclosingNodeOrSelfWithClass('style-panes-wrapper');
if (this._scrollerElement) {
this._scrollerElement.addEventListener('scroll', this._boundOnScroll, false);
}
this._parentPane.setEditingStyle(true);
}
_onScroll() {
this._swatchPopoverHelper.hide(true);
}
_onPopoverHidden() {
if (this._scrollerElement) {
this._scrollerElement.removeEventListener('scroll', this._boundOnScroll, false);
}
this._section.onpopulate();
if (this._fontEditor) {
this._fontEditor.removeEventListener(InlineEditor.FontEditor.Events.FontChanged, this._boundFontChanged);
}
this._fontEditor = null;
if (this._parentPane) {
this._parentPane.setEditingStyle(false);
}
this._section.resetToolbars();
this._section.onpopulate();
}
// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
// eslint-disable-next-line @typescript-eslint/naming-convention
static _treeElementSymbol = Symbol('FontEditorSectionManager._treeElementSymbol');
}