allow device cards to collapse
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
94
www/src/ts/components/details.ts
Normal file
94
www/src/ts/components/details.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { html, css, HTMLTemplateResult, PropertyValueMap } from "lit";
|
||||
import { customElement, query, state } from "lit/decorators.js";
|
||||
import { classMap } from "lit/directives/class-map.js";
|
||||
import SlDetails from "@shoelace-style/shoelace/dist/components/details/details.js";
|
||||
|
||||
@customElement("ic10-details")
|
||||
export class IC10Details extends SlDetails {
|
||||
@query(".details__summary-icon") accessor summaryIcon: HTMLSpanElement;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
private handleSummaryIconClick(event: MouseEvent) {
|
||||
event.preventDefault();
|
||||
|
||||
if (!this.disabled) {
|
||||
if (this.open) {
|
||||
this.hide();
|
||||
} else {
|
||||
this.show();
|
||||
}
|
||||
this.header.focus();
|
||||
}
|
||||
}
|
||||
|
||||
private handleSummaryIconKeyDown(event: KeyboardEvent) {
|
||||
if (event.key === "Enter" || event.key === " ") {
|
||||
event.preventDefault();
|
||||
|
||||
if (this.open) {
|
||||
this.hide();
|
||||
} else {
|
||||
this.show();
|
||||
}
|
||||
}
|
||||
|
||||
if (event.key === "ArrowUp" || event.key === "ArrowLeft") {
|
||||
event.preventDefault();
|
||||
this.hide();
|
||||
}
|
||||
|
||||
if (event.key === "ArrowDown" || event.key === "ArrowRight") {
|
||||
event.preventDefault();
|
||||
this.show();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<details
|
||||
part="base"
|
||||
class=${classMap({
|
||||
details: true,
|
||||
"details--open": this.open,
|
||||
"details--disabled": this.disabled,
|
||||
})}
|
||||
>
|
||||
<summary
|
||||
part="header"
|
||||
id="header"
|
||||
class="details__header"
|
||||
role="button"
|
||||
aria-expanded=${this.open ? "true" : "false"}
|
||||
aria-controls="content"
|
||||
aria-disabled=${this.disabled ? "true" : "false"}
|
||||
tabindex=${this.disabled ? "-1" : "0"}
|
||||
>
|
||||
<slot name="summary" part="summary" class="details__summary"
|
||||
>${this.summary}</slot
|
||||
>
|
||||
|
||||
<span
|
||||
part="summary-icon"
|
||||
class="details__summary-icon"
|
||||
@click=${this.handleSummaryIconClick}
|
||||
@keydown=${this.handleSummaryIconKeyDown}
|
||||
>
|
||||
<slot name="expand-icon">
|
||||
<sl-icon library="system" name="chevron-right"></sl-icon>
|
||||
</slot>
|
||||
<slot name="collapse-icon">
|
||||
<sl-icon library="system" name="chevron-right"></sl-icon>
|
||||
</slot>
|
||||
</span>
|
||||
</summary>
|
||||
|
||||
<div class="details__body" role="region" aria-labelledby="header">
|
||||
<slot part="content" id="content" class="details__content"></slot>
|
||||
</div>
|
||||
</details>
|
||||
`;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
import { BaseElement, defaultCss } from './base';
|
||||
|
||||
export { BaseElement, defaultCss }
|
||||
import { IC10Details } from './details';
|
||||
export { BaseElement, defaultCss, IC10Details }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { property, state } from "lit/decorators.js";
|
||||
import { BaseElement } from "../components";
|
||||
|
||||
import {
|
||||
DeviceRef,
|
||||
Fields,
|
||||
@@ -14,151 +14,179 @@ import {
|
||||
Pins,
|
||||
} from "ic10emu_wasm";
|
||||
import { structuralEqual } from "../utils";
|
||||
import { LitElement } from "lit";
|
||||
import { BaseElement } from "../components/base";
|
||||
|
||||
export class VMBaseDevice extends BaseElement {
|
||||
@property({ type: Number }) accessor deviceID: number;
|
||||
@state() protected accessor device: DeviceRef;
|
||||
type Constructor<T = {}> = new (...args: any[]) => T;
|
||||
|
||||
@state() accessor name: string | null;
|
||||
@state() accessor nameHash: number | null;
|
||||
@state() accessor prefabName: string | null;
|
||||
@state() accessor fields: Fields;
|
||||
@state() accessor slots: Slot[];
|
||||
@state() accessor reagents: Reagents;
|
||||
@state() accessor connections: Connection[];
|
||||
@state() accessor icIP: number;
|
||||
@state() accessor icOpCount: number;
|
||||
@state() accessor icState: string;
|
||||
@state() accessor errors: ICError[];
|
||||
@state() accessor registers: Registers | null;
|
||||
@state() accessor stack: Stack | null;
|
||||
@state() accessor aliases: Aliases | null;
|
||||
@state() accessor defines: Defines | null;
|
||||
@state() accessor pins: Pins | null;
|
||||
export declare class VMDeviceMixinInterface {
|
||||
deviceID: number;
|
||||
device: DeviceRef;
|
||||
name: string | null;
|
||||
nameHash: number | null;
|
||||
prefabName: string | null;
|
||||
fields: Fields;
|
||||
slots: Slot[];
|
||||
reagents: Reagents;
|
||||
connections: Connection[];
|
||||
icIP: number;
|
||||
icOpCount: number;
|
||||
icState: string;
|
||||
errors: ICError[];
|
||||
registers: Registers | null;
|
||||
stack: Stack | null;
|
||||
aliases: Aliases | null;
|
||||
defines: Defines | null;
|
||||
pins: Pins | null;
|
||||
_handleDeviceModified(e: CustomEvent): void;
|
||||
updateDevice(): void;
|
||||
updateIC(): void;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.name = null;
|
||||
this.nameHash = null;
|
||||
export const VMDeviceMixin = <T extends Constructor<LitElement>>(
|
||||
superClass: T,
|
||||
) => {
|
||||
class VMDeviceMixinClass extends superClass {
|
||||
@property({ type: Number }) accessor deviceID: number;
|
||||
@state() accessor device: DeviceRef;
|
||||
|
||||
@state() accessor name: string | null = null;
|
||||
@state() accessor nameHash: number | null = null;
|
||||
@state() accessor prefabName: string | null;
|
||||
@state() accessor fields: Fields;
|
||||
@state() accessor slots: Slot[];
|
||||
@state() accessor reagents: Reagents;
|
||||
@state() accessor connections: Connection[];
|
||||
@state() accessor icIP: number;
|
||||
@state() accessor icOpCount: number;
|
||||
@state() accessor icState: string;
|
||||
@state() accessor errors: ICError[];
|
||||
@state() accessor registers: Registers | null;
|
||||
@state() accessor stack: Stack | null;
|
||||
@state() accessor aliases: Aliases | null;
|
||||
@state() accessor defines: Defines | null;
|
||||
@state() accessor pins: Pins | null;
|
||||
|
||||
connectedCallback(): void {
|
||||
const root = super.connectedCallback();
|
||||
this.device = window.VM!.devices.get(this.deviceID)!;
|
||||
window.VM?.addEventListener(
|
||||
"vm-device-modified",
|
||||
this._handleDeviceModified.bind(this),
|
||||
);
|
||||
this.updateDevice();
|
||||
return root;
|
||||
}
|
||||
|
||||
_handleDeviceModified(e: CustomEvent) {
|
||||
const id = e.detail;
|
||||
if (this.deviceID === id) {
|
||||
this.updateDevice();
|
||||
}
|
||||
}
|
||||
|
||||
updateDevice() {
|
||||
const name = this.device.name ?? null;
|
||||
if (this.name !== name) {
|
||||
this.name = name;
|
||||
}
|
||||
const nameHash = this.device.nameHash ?? null;
|
||||
if (this.nameHash !== nameHash) {
|
||||
this.nameHash = nameHash;
|
||||
}
|
||||
const prefabName = this.device.prefabName ?? null;
|
||||
if (this.prefabName !== prefabName) {
|
||||
this.prefabName = prefabName;
|
||||
}
|
||||
const fields = this.device.fields;
|
||||
if (!structuralEqual(this.fields, fields)) {
|
||||
this.fields = fields;
|
||||
}
|
||||
const slots = this.device.slots;
|
||||
if (!structuralEqual(this.slots, slots)) {
|
||||
this.slots = slots;
|
||||
}
|
||||
const reagents = this.device.reagents;
|
||||
if (!structuralEqual(this.reagents, reagents)) {
|
||||
this.reagents = reagents;
|
||||
}
|
||||
const connections = this.device.connections;
|
||||
if (!structuralEqual(this.connections, connections)) {
|
||||
this.connections = connections;
|
||||
}
|
||||
this.updateIC();
|
||||
}
|
||||
|
||||
updateIC() {
|
||||
const ip = this.device.ip!;
|
||||
if (this.icIP !== ip) {
|
||||
this.icIP = ip;
|
||||
}
|
||||
const opCount = this.device.instructionCount!;
|
||||
if (this.icOpCount !== opCount) {
|
||||
this.icOpCount = opCount;
|
||||
}
|
||||
const state = this.device.state!;
|
||||
if (this.icState !== state) {
|
||||
this.icState = state;
|
||||
}
|
||||
const errors = this.device.program!.errors ?? null;
|
||||
if (!structuralEqual(this.errors, errors)) {
|
||||
this.errors = errors;
|
||||
}
|
||||
const registers = this.device.registers ?? null;
|
||||
if (!structuralEqual(this.registers, registers)) {
|
||||
this.registers = registers;
|
||||
}
|
||||
const stack = this.device.stack ?? null;
|
||||
if (!structuralEqual(this.stack, stack)) {
|
||||
this.stack = stack;
|
||||
}
|
||||
const aliases = this.device.aliases ?? null;
|
||||
if (!structuralEqual(this.aliases, aliases)) {
|
||||
this.aliases = aliases;
|
||||
}
|
||||
const defines = this.device.defines ?? null;
|
||||
if (!structuralEqual(this.defines, defines)) {
|
||||
this.defines = defines;
|
||||
}
|
||||
const pins = this.device.pins ?? null;
|
||||
if (!structuralEqual(this.pins, pins)) {
|
||||
this.pins = pins;
|
||||
}
|
||||
}
|
||||
}
|
||||
return VMDeviceMixinClass as Constructor<VMDeviceMixinInterface> & T;
|
||||
};
|
||||
|
||||
connectedCallback(): void {
|
||||
const root = super.connectedCallback();
|
||||
this.device = window.VM!.devices.get(this.deviceID)!;
|
||||
window.VM?.addEventListener(
|
||||
"vm-device-modified",
|
||||
this._handleDeviceModified.bind(this),
|
||||
);
|
||||
this.updateDevice();
|
||||
return root;
|
||||
}
|
||||
export const VMActiveICMixin = <T extends Constructor<LitElement>>(superClass: T) => {
|
||||
class VMActiveICMixinClass extends VMDeviceMixin(superClass) {
|
||||
constructor() {
|
||||
super();
|
||||
this.deviceID = window.App!.session.activeIC;
|
||||
}
|
||||
|
||||
_handleDeviceModified(e: CustomEvent) {
|
||||
const id = e.detail;
|
||||
if (this.deviceID === id) {
|
||||
connectedCallback(): void {
|
||||
const root = super.connectedCallback();
|
||||
window.VM?.addEventListener(
|
||||
"vm-run-ic",
|
||||
this._handleDeviceModified.bind(this),
|
||||
);
|
||||
window.App?.session.addEventListener(
|
||||
"session-active-ic",
|
||||
this._handleActiveIC.bind(this),
|
||||
);
|
||||
return root;
|
||||
}
|
||||
|
||||
_handleActiveIC(e: CustomEvent) {
|
||||
const id = e.detail;
|
||||
if (this.deviceID !== id) {
|
||||
this.deviceID = id;
|
||||
this.device = window.VM!.devices.get(this.deviceID)!;
|
||||
}
|
||||
this.updateDevice();
|
||||
}
|
||||
}
|
||||
|
||||
updateDevice() {
|
||||
const name = this.device.name ?? null;
|
||||
if (this.name !== name) {
|
||||
this.name = name;
|
||||
}
|
||||
const nameHash = this.device.nameHash ?? null;
|
||||
if (this.nameHash !== nameHash) {
|
||||
this.nameHash = nameHash;
|
||||
}
|
||||
const prefabName = this.device.prefabName ?? null;
|
||||
if (this.prefabName !== prefabName) {
|
||||
this.prefabName = prefabName;
|
||||
}
|
||||
const fields = this.device.fields;
|
||||
if (!structuralEqual(this.fields, fields)) {
|
||||
this.fields = fields;
|
||||
}
|
||||
const slots = this.device.slots;
|
||||
if (!structuralEqual(this.slots, slots)) {
|
||||
this.slots = slots;
|
||||
}
|
||||
const reagents = this.device.reagents;
|
||||
if (!structuralEqual(this.reagents, reagents)) {
|
||||
this.reagents = reagents;
|
||||
}
|
||||
const connections = this.device.connections;
|
||||
if (!structuralEqual(this.connections, connections)) {
|
||||
this.connections = connections;
|
||||
}
|
||||
this.updateIC();
|
||||
}
|
||||
|
||||
updateIC() {
|
||||
const ip = this.device.ip!;
|
||||
if (this.icIP !== ip) {
|
||||
this.icIP = ip;
|
||||
}
|
||||
const opCount = this.device.instructionCount!;
|
||||
if (this.icOpCount !== opCount) {
|
||||
this.icOpCount = opCount;
|
||||
}
|
||||
const state = this.device.state!;
|
||||
if (this.icState !== state) {
|
||||
this.icState = state;
|
||||
}
|
||||
const errors = this.device.program!.errors ?? null;
|
||||
if (!structuralEqual(this.errors, errors)) {
|
||||
this.errors = errors;
|
||||
}
|
||||
const registers = this.device.registers ?? null;
|
||||
if (!structuralEqual(this.registers, registers)) {
|
||||
this.registers = registers;
|
||||
}
|
||||
const stack = this.device.stack ?? null;
|
||||
if (!structuralEqual(this.stack, stack)) {
|
||||
this.stack = stack;
|
||||
}
|
||||
const aliases = this.device.aliases ?? null;
|
||||
if (!structuralEqual(this.aliases, aliases)) {
|
||||
this.aliases = aliases;
|
||||
}
|
||||
const defines = this.device.defines ?? null;
|
||||
if (!structuralEqual(this.defines, defines)) {
|
||||
this.defines = defines;
|
||||
}
|
||||
const pins = this.device.pins ?? null;
|
||||
if(!structuralEqual(this.pins, pins)) {
|
||||
this.pins = pins;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class VMActiveIC extends VMBaseDevice {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.deviceID = window.App!.session.activeIC;
|
||||
}
|
||||
|
||||
connectedCallback(): void {
|
||||
const root = super.connectedCallback();
|
||||
window.VM?.addEventListener(
|
||||
"vm-run-ic",
|
||||
this._handleDeviceModified.bind(this),
|
||||
);
|
||||
window.App?.session.addEventListener(
|
||||
"session-active-ic",
|
||||
this._handleActiveIC.bind(this),
|
||||
);
|
||||
return root;
|
||||
}
|
||||
|
||||
_handleActiveIC(e: CustomEvent) {
|
||||
const id = e.detail;
|
||||
if (this.deviceID !== id) {
|
||||
this.deviceID = id;
|
||||
this.device = window.VM!.devices.get(this.deviceID)!;
|
||||
}
|
||||
this.updateDevice();
|
||||
}
|
||||
|
||||
};
|
||||
return VMActiveICMixinClass as Constructor<VMDeviceMixinInterface> & T;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { html, css } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
import { defaultCss } from "../components";
|
||||
import { VMActiveIC } from "./base_device";
|
||||
import { BaseElement, defaultCss } from "../components";
|
||||
import { VMActiveICMixin } from "./base_device";
|
||||
import { structuralEqual } from "../utils";
|
||||
|
||||
import "@shoelace-style/shoelace/dist/components/card/card.js";
|
||||
@@ -16,7 +16,7 @@ import "@shoelace-style/shoelace/dist/components/option/option.js";
|
||||
import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.js";
|
||||
|
||||
@customElement("vm-ic-controls")
|
||||
export class VMICControls extends VMActiveIC {
|
||||
export class VMICControls extends VMActiveICMixin(BaseElement) {
|
||||
static styles = [
|
||||
...defaultCss,
|
||||
css`
|
||||
@@ -121,11 +121,11 @@ export class VMICControls extends VMActiveIC {
|
||||
@sl-change=${this._handleChangeActiveIC}
|
||||
>
|
||||
${ics.map(
|
||||
([id, device], _index) =>
|
||||
html`<sl-option value=${id}>
|
||||
([id, device], _index) =>
|
||||
html`<sl-option value=${id}>
|
||||
Device:${id} ${device.name ?? device.prefabName}
|
||||
</sl-option>`,
|
||||
)}
|
||||
)}
|
||||
</sl-select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -148,15 +148,15 @@ export class VMICControls extends VMActiveIC {
|
||||
<div class="vstack">
|
||||
<span>Errors</span>
|
||||
${this.errors.map(
|
||||
(err) =>
|
||||
html`<div class="hstack">
|
||||
(err) =>
|
||||
html`<div class="hstack">
|
||||
<span>
|
||||
Line: ${err.ParseError.line} -
|
||||
${err.ParseError.start}:${err.ParseError.end}
|
||||
</span>
|
||||
<span class="ms-auto">${err.ParseError.msg}</span>
|
||||
</div>`,
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</sl-card>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Slot } from "ic10emu_wasm";
|
||||
import { html, css, HTMLTemplateResult } from "lit";
|
||||
import { html, css, HTMLTemplateResult, PropertyValueMap } from "lit";
|
||||
import { customElement, state } from "lit/decorators.js";
|
||||
import { BaseElement, defaultCss } from "../components";
|
||||
import { VMBaseDevice } from "./base_device";
|
||||
import { BaseElement, defaultCss, IC10Details } from "../components";
|
||||
import { VMDeviceMixin } from "./base_device";
|
||||
|
||||
import "@shoelace-style/shoelace/dist/components/card/card.js";
|
||||
import "@shoelace-style/shoelace/dist/components/icon/icon.js";
|
||||
@@ -19,9 +19,10 @@ import "@shoelace-style/shoelace/dist/components/option/option.js";
|
||||
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
|
||||
import { parseNumber, structuralEqual } from "../utils";
|
||||
import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.js";
|
||||
import SlDetails from "@shoelace-style/shoelace/dist/components/details/details.js";
|
||||
|
||||
@customElement("vm-device-card")
|
||||
export class VMDeviceCard extends VMBaseDevice {
|
||||
export class VMDeviceCard extends VMDeviceMixin(BaseElement) {
|
||||
image_err: boolean;
|
||||
|
||||
static styles = [
|
||||
@@ -51,14 +52,12 @@ export class VMDeviceCard extends VMBaseDevice {
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
// .device-name {
|
||||
// box-sizing: border-box;
|
||||
// width: 8rem;
|
||||
// }
|
||||
// .device-name-hash {
|
||||
// box-sizing: border-box;
|
||||
// width: 5rem;
|
||||
// }
|
||||
.device-name::part(input) {
|
||||
width: 10rem;
|
||||
}
|
||||
.device-name-hash::part(input) {
|
||||
width: 7rem;
|
||||
}
|
||||
sl-divider {
|
||||
--spacing: 0.25rem;
|
||||
}
|
||||
@@ -129,7 +128,7 @@ export class VMDeviceCard extends VMBaseDevice {
|
||||
value="${this.nameHash}"
|
||||
disabled
|
||||
>
|
||||
<span slot="prefix">Name Hash</span>
|
||||
<span slot="prefix">Hash</span>
|
||||
<sl-copy-button
|
||||
slot="suffix"
|
||||
from="vmDeviceCard${this.deviceID}NameHash.value"
|
||||
@@ -195,6 +194,7 @@ export class VMDeviceCard extends VMBaseDevice {
|
||||
</sl-card>
|
||||
`;
|
||||
}
|
||||
|
||||
renderSlots(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div clas="slots">
|
||||
@@ -202,9 +202,11 @@ export class VMDeviceCard extends VMBaseDevice {
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
renderReagents(): HTMLTemplateResult {
|
||||
return html``;
|
||||
}
|
||||
|
||||
renderNetworks(): HTMLTemplateResult {
|
||||
const vmNetworks = window.VM!.networks;
|
||||
return html`
|
||||
@@ -260,10 +262,11 @@ export class VMDeviceCard extends VMBaseDevice {
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
protected render(): HTMLTemplateResult {
|
||||
|
||||
render(): HTMLTemplateResult {
|
||||
return html`
|
||||
<sl-card class="card">
|
||||
<div class="header" slot="header">${this.renderHeader()}</div>
|
||||
<ic10-details class="device-card" open>
|
||||
<div class="header" slot="summary">${this.renderHeader()}</div>
|
||||
<sl-tab-group>
|
||||
<sl-tab slot="nav" panel="fields">Fields</sl-tab>
|
||||
<sl-tab slot="nav" panel="slots">Slots</sl-tab>
|
||||
@@ -277,7 +280,7 @@ export class VMDeviceCard extends VMBaseDevice {
|
||||
<sl-tab-panel name="networks">${this.renderNetworks()}</sl-tab-panel>
|
||||
<sl-tab-panel name="pins">${this.renderPins()}</sl-tab-panel>
|
||||
</sl-tab-group>
|
||||
</sl-card>
|
||||
</ic10-details>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -341,6 +344,19 @@ export class VMDeviceCard extends VMBaseDevice {
|
||||
export class VMDeviceList extends BaseElement {
|
||||
@state() accessor devices: number[];
|
||||
|
||||
static styles = [
|
||||
...defaultCss,
|
||||
css`
|
||||
.device-list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.device-list-card {
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.devices = window.VM!.deviceIds;
|
||||
@@ -367,7 +383,10 @@ export class VMDeviceList extends BaseElement {
|
||||
<div class="device-list">
|
||||
${this.devices.map(
|
||||
(id, _index, _ids) =>
|
||||
html`<vm-device-card .deviceID=${id}></vm-device-card>`,
|
||||
html`<vm-device-card
|
||||
.deviceID=${id}
|
||||
class="device-list-card"
|
||||
></vm-device-card>`,
|
||||
)}
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { html, css } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
import { defaultCss } from "../components";
|
||||
import { VMActiveIC } from "./base_device";
|
||||
import { BaseElement, defaultCss } from "../components";
|
||||
import { VMActiveICMixin } from "./base_device";
|
||||
|
||||
import "@shoelace-style/shoelace/dist/components/card/card.js";
|
||||
import "@shoelace-style/shoelace/dist/components/icon/icon.js";
|
||||
@@ -12,7 +12,7 @@ import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
|
||||
import { parseNumber } from "../utils";
|
||||
|
||||
@customElement("vm-ic-registers")
|
||||
export class VMICRegisters extends VMActiveIC {
|
||||
export class VMICRegisters extends VMActiveICMixin(BaseElement) {
|
||||
static styles = [
|
||||
...defaultCss,
|
||||
css`
|
||||
@@ -57,8 +57,6 @@ export class VMICRegisters extends VMActiveIC {
|
||||
return val.toString();
|
||||
}
|
||||
};
|
||||
const validation =
|
||||
"[\\-+]?(([0-9]+(\\.[0-9]+)?([eE][\\-+]?[0-9]+)?)|((\\.[0-9]+)([eE][\\-+]?[0-9]+)?)|([iI][nN][fF][iI][nN][iI][tT][yY]))";
|
||||
const registerAliases: [string, number][] = (
|
||||
(
|
||||
[...(this.aliases ?? [])].filter(
|
||||
@@ -74,19 +72,18 @@ export class VMICRegisters extends VMActiveIC {
|
||||
<sl-card class="card">
|
||||
<div class="card-body">
|
||||
${this.registers?.map((val, index) => {
|
||||
const aliases = registerAliases
|
||||
.filter(([_alias, target]) => index === target)
|
||||
.map(([alias, _target]) => alias);
|
||||
return html`
|
||||
const aliases = registerAliases
|
||||
.filter(([_alias, target]) => index === target)
|
||||
.map(([alias, _target]) => alias);
|
||||
return html`
|
||||
<sl-tooltip placement="left" class="tooltip">
|
||||
<div slot="content">
|
||||
<strong>Regster r${index}</strong> Aliases:
|
||||
<strong>Register r${index}</strong> Aliases:
|
||||
<em>${aliases.join(", ") || "None"}</em>
|
||||
</div>
|
||||
<sl-input
|
||||
type="text"
|
||||
value="${displayVal(val)}"
|
||||
pattern="${validation}"
|
||||
size="small"
|
||||
class="reg-input"
|
||||
@sl-change=${this._handleCellChange}
|
||||
@@ -97,7 +94,7 @@ export class VMICRegisters extends VMActiveIC {
|
||||
</sl-input>
|
||||
</sl-tooltip>
|
||||
`;
|
||||
})}
|
||||
})}
|
||||
</div>
|
||||
</sl-card>
|
||||
`;
|
||||
@@ -106,7 +103,7 @@ export class VMICRegisters extends VMActiveIC {
|
||||
_handleCellChange(e: Event) {
|
||||
const input = e.target as SlInput;
|
||||
const index = parseInt(input.getAttribute("key")!);
|
||||
const val = parseNumber(input.value)
|
||||
const val = parseNumber(input.value);
|
||||
window.VM!.setRegister(index, val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { html, css } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
import { defaultCss } from "../components";
|
||||
import { VMActiveIC } from "./base_device";
|
||||
import { BaseElement, defaultCss } from "../components";
|
||||
import { VMActiveICMixin } from "./base_device";
|
||||
|
||||
import "@shoelace-style/shoelace/dist/components/card/card.js";
|
||||
import "@shoelace-style/shoelace/dist/components/icon/icon.js";
|
||||
@@ -11,7 +11,7 @@ import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
|
||||
import { parseNumber } from "../utils";
|
||||
|
||||
@customElement("vm-ic-stack")
|
||||
export class VMICStack extends VMActiveIC {
|
||||
export class VMICStack extends VMActiveICMixin(BaseElement) {
|
||||
static styles = [
|
||||
...defaultCss,
|
||||
css`
|
||||
@@ -53,8 +53,6 @@ export class VMICStack extends VMActiveIC {
|
||||
return val.toString();
|
||||
}
|
||||
};
|
||||
const validation =
|
||||
"[\\-+]?(([0-9]+(\\.[0-9]+)?([eE][\\-+]?[0-9]+)?)|((\\.[0-9]+)([eE][\\-+]?[0-9]+)?)|([iI][nN][fF][iI][nN][iI][tT][yY]))";
|
||||
const sp = this.registers![16];
|
||||
|
||||
return html`
|
||||
@@ -62,17 +60,14 @@ export class VMICStack extends VMActiveIC {
|
||||
<div class="card-body">
|
||||
${this.stack?.map((val, index) => {
|
||||
return html`
|
||||
<sl-tooltip
|
||||
placement="left"
|
||||
>
|
||||
<sl-tooltip placement="left">
|
||||
<div slot="content">
|
||||
${sp === index ? html`<strong>Stack Pointer</strong>` : ""}
|
||||
Address ${index}
|
||||
${sp === index ? html`<strong>Stack Pointer</strong>` : ""}
|
||||
Address ${index}
|
||||
</div>
|
||||
<sl-input
|
||||
type="text"
|
||||
value="${displayVal(val)}"
|
||||
pattern="${validation}"
|
||||
size="small"
|
||||
class="stack-input ${sp === index ? "stack-pointer" : ""}"
|
||||
@sl-change=${this._handleCellChange}
|
||||
@@ -91,7 +86,7 @@ export class VMICStack extends VMActiveIC {
|
||||
_handleCellChange(e: Event) {
|
||||
const input = e.target as SlInput;
|
||||
const index = parseInt(input.getAttribute("key")!);
|
||||
const val = parseNumber(input.value)
|
||||
const val = parseNumber(input.value);
|
||||
window.VM!.setStack(index, val);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user