@quick-game/cli
Version:
Command line interface for rapid qg development
153 lines • 5.92 kB
JavaScript
// Copyright 2021 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.
import * as IconButton from '../../ui/components/icon_button/icon_button.js';
import * as UI from '../../ui/legacy/legacy.js';
import { StylePropertyTreeElement } from './StylePropertyTreeElement.js';
let instance = null;
/**
* Thin UI.Widget wrapper around style editors to allow using it as a popover.
*/
export class StyleEditorWidget extends UI.Widget.VBox {
editor;
pane;
section;
editorContainer;
#triggerKey;
constructor() {
super(true);
this.contentElement.tabIndex = 0;
this.setDefaultFocusedElement(this.contentElement);
this.editorContainer = document.createElement('div');
this.contentElement.appendChild(this.editorContainer);
this.onPropertySelected = this.onPropertySelected.bind(this);
this.onPropertyDeselected = this.onPropertyDeselected.bind(this);
}
getSection() {
return this.section;
}
async onPropertySelected(event) {
if (!this.section) {
return;
}
const target = ensureTreeElementForProperty(this.section, event.data.name);
target.property.value = event.data.value;
target.updateTitle();
await target.applyStyleText(target.renderedPropertyText(), false);
await this.render();
}
async onPropertyDeselected(event) {
if (!this.section) {
return;
}
const target = ensureTreeElementForProperty(this.section, event.data.name);
await target.applyStyleText('', false);
await this.render();
}
bindContext(pane, section) {
this.pane = pane;
this.section = section;
this.editor?.addEventListener('propertyselected', this.onPropertySelected);
this.editor?.addEventListener('propertydeselected', this.onPropertyDeselected);
}
setTriggerKey(value) {
this.#triggerKey = value;
}
getTriggerKey() {
return this.#triggerKey;
}
unbindContext() {
this.pane = undefined;
this.section = undefined;
this.editor?.removeEventListener('propertyselected', this.onPropertySelected);
this.editor?.removeEventListener('propertydeselected', this.onPropertyDeselected);
}
async render() {
if (!this.editor) {
return;
}
this.editor.data = {
authoredProperties: this.section ? getAuthoredStyles(this.section, this.editor.getEditableProperties()) :
new Map(),
computedProperties: this.pane ? await fetchComputedStyles(this.pane) : new Map(),
};
}
static instance() {
if (!instance) {
instance = new StyleEditorWidget();
}
return instance;
}
setEditor(editorClass) {
if (!(this.editor instanceof editorClass)) {
this.contentElement.removeChildren();
this.editor = new editorClass();
this.contentElement.appendChild(this.editor);
}
}
static createTriggerButton(pane, section, editorClass, buttonTitle, triggerKey) {
const triggerButton = createButton(buttonTitle);
triggerButton.onclick = async (event) => {
event.stopPropagation();
const popoverHelper = pane.swatchPopoverHelper();
const widget = StyleEditorWidget.instance();
widget.setEditor(editorClass);
widget.bindContext(pane, section);
widget.setTriggerKey(triggerKey);
await widget.render();
const scrollerElement = triggerButton.enclosingNodeOrSelfWithClass('style-panes-wrapper');
const onScroll = () => {
popoverHelper.hide(true);
};
popoverHelper.show(widget, triggerButton, () => {
widget.unbindContext();
if (scrollerElement) {
scrollerElement.removeEventListener('scroll', onScroll);
}
});
if (scrollerElement) {
scrollerElement.addEventListener('scroll', onScroll);
}
};
return triggerButton;
}
}
function createButton(buttonTitle) {
const button = document.createElement('button');
button.classList.add('styles-pane-button');
button.tabIndex = 0;
button.title = buttonTitle;
button.onmouseup = (event) => {
// Stop propagation to prevent the property editor from being activated.
event.stopPropagation();
};
const icon = new IconButton.Icon.Icon();
icon.data = { iconName: 'flex-wrap', color: 'var(--color-text-secondary)', width: '16px', height: '16px' };
button.appendChild(icon);
return button;
}
function ensureTreeElementForProperty(section, propertyName) {
const target = section.propertiesTreeOutline.rootElement().children().find(child => child instanceof StylePropertyTreeElement && child.property.name === propertyName);
if (target) {
return target;
}
const newTarget = section.addNewBlankProperty();
newTarget.property.name = propertyName;
return newTarget;
}
async function fetchComputedStyles(pane) {
const computedStyleModel = pane.computedStyleModel();
const style = await computedStyleModel.fetchComputedStyle();
return style ? style.computedStyle : new Map();
}
function getAuthoredStyles(section, editableProperties) {
const authoredProperties = new Map();
const editablePropertiesSet = new Set(editableProperties.map(prop => prop.propertyName));
for (const prop of section.style().leadingProperties()) {
if (editablePropertiesSet.has(prop.name)) {
authoredProperties.set(prop.name, prop.value);
}
}
return authoredProperties;
}
//# sourceMappingURL=StyleEditorWidget.js.map