UNPKG

@dark-engine/platform-desktop

Version:

Dark renderer to desktop platforms like Windows, Linux, macOS via Nodegui and Qt

184 lines (183 loc) 5.64 kB
import { QWidget } from '@nodegui/nodegui'; import { NodeType, ROOT, detectIsFunction } from '@dark-engine/core'; import { createSetterName, detectIsContainer } from '../utils'; import { createSyntheticEventHandler } from '../events'; import { getElementFactory } from '../registry'; import { TEXT_ATTR } from '../constants'; class NativeElement { type; parentElement = null; constructor(type) { this.type = type; } getText() { return this.type; } } class TagNativeElement extends NativeElement { name = null; attrs = {}; children = []; nativeView; eventListeners = new Map(); constructor(name) { super(NodeType.TAG); this.name = name; this.nativeView = getElementFactory(name).create(); } getNativeView() { if (this.name === ROOT) { const tag = this.children[0]; return tag.getNativeView(); } return this.nativeView; } appendChild(element) { element.parentElement = this; this.children.push(element); if (element.type === NodeType.TAG) { const parent = this.nativeView; const child = element.getNativeView(); detectIsContainer(parent) && parent.appendChild(child); } else if (element.type === NodeType.TEXT) { this.updateText(); } } insertBefore(element, siblingElement) { if (!siblingElement) { return this.appendChild(element); } const idx = this.children.findIndex(node => node === siblingElement); if (idx === -1) { return this.appendChild(element); } if (element.parentElement) { element.parentElement.removeChild(element); } this.children.splice(idx, 0, element); element.parentElement = this; if (element.type === NodeType.TAG) { const parent = this.nativeView; const child = element.getNativeView(); const sibling = siblingElement.getNativeView(); const idx = this.children.filter(node => node.type === NodeType.TAG).findIndex(node => node === element); detectIsContainer(parent) && parent.insertBefore(child, sibling, idx); } else if (element.type === NodeType.TEXT) { this.updateText(); } } removeChild(element) { const idx = this.children.findIndex(node => node === element); if (idx !== -1) { this.children.splice(idx, 1); element.parentElement = null; if (element.type === NodeType.TAG) { const parent = this.nativeView; const child = element.getNativeView(); detectIsContainer(parent) && parent.removeChild(child); } else if (element.type === NodeType.TEXT) { this.updateText(); } } } getAttribute(name) { return this.attrs[name]; } setAttribute(name, value) { const setterName = createSetterName(name); defaultAttrSetter(this, name, value); if (!detectIsFunction(this.nativeView[setterName])) return; if (!this.nativeView[INITIAL_ATTR_VALUE]) { this.nativeView[INITIAL_ATTR_VALUE] = {}; } this.nativeView[INITIAL_ATTR_VALUE][name] = this.nativeView[name]; this.nativeView[setterName](value); this.attrs[name] = value; } removeAttribute(name) { const setterName = createSetterName(name); if (!detectIsFunction(this.nativeView[setterName])) return; const initialValue = this.nativeView[INITIAL_ATTR_VALUE][name]; this.nativeView[setterName](initialValue); delete this.nativeView[INITIAL_ATTR_VALUE][name]; delete this.attrs[name]; } updateText() { let text = ''; for (const child of this.children) { if (child.type === NodeType.TEXT) { text += child.value; } } this.setAttribute(TEXT_ATTR, text); } getText() { return this.getAttribute(TEXT_ATTR); } addEventListener(eventName, handler) { const syntheticHandler = createSyntheticEventHandler(eventName, handler); this.removeEventListener(eventName); this.eventListeners.set(eventName, syntheticHandler); this.nativeView.addEventListener(eventName, syntheticHandler); } removeEventListener(eventName) { const handler = this.eventListeners.get(eventName); this.eventListeners.delete(eventName); this.nativeView.removeEventListener(eventName, handler); } } class TextNativeElement extends NativeElement { _value = ''; constructor(text) { super(NodeType.TEXT); this._value = text; } get value() { return this._value; } set value(value) { this._value = value; if (this.parentElement?.type === NodeType.TAG) { this.parentElement.updateText(); } } getText() { return this._value; } } class CommentNativeElement extends NativeElement { _value = ''; constructor(text) { super(NodeType.COMMENT); this._value = `<!--${text}-->`; } get value() { return this._value; } set value(value) { this._value = value; } getText() { return this._value; } } function createAttrSetter(setter) { const map = { id: (w, n) => w.setObjectName(n), posX: (w, n) => w.move(n, w.y()), posY: (w, n) => w.move(w.x(), n), width: (w, n) => w.resize(n, w.height()), height: (w, n) => w.resize(w.width(), n), style: (w, n) => w.setInlineStyle(n), ...setter, }; return (element, name, value) => { const widget = element.getNativeView(); if (!QWidget.isPrototypeOf(widget) && !(widget instanceof QWidget)) return; map[name] && map[name](widget, value); }; } const defaultAttrSetter = createAttrSetter({}); export const INITIAL_ATTR_VALUE = '_INITIAL_ATTR_VALUE'; export { NativeElement, TagNativeElement, TextNativeElement, CommentNativeElement, createAttrSetter }; //# sourceMappingURL=native-element.js.map