make sure device pins can be set and fix device update events for device removal

This commit is contained in:
Rachel Powers
2024-04-28 14:56:49 -07:00
parent fc0729cad3
commit 078e2bb05a
4 changed files with 105 additions and 27 deletions

View File

@@ -59,7 +59,8 @@ export type VMDeviceMixinSubscription =
| "ic"
| "active-ic"
| { field: LogicType }
| { slot: number };
| { slot: number }
| "visible-devices";
export const VMDeviceMixin = <T extends Constructor<LitElement>>(
superClass: T,
@@ -124,6 +125,10 @@ export const VMDeviceMixin = <T extends Constructor<LitElement>>(
"vm-device-id-change",
this._handleDeviceIdChange.bind(this),
);
vm.addEventListener(
"vm-devices-removed",
this._handleDevicesRemoved.bind(this),
)
});
this.updateDevice();
return root;
@@ -143,6 +148,10 @@ export const VMDeviceMixin = <T extends Constructor<LitElement>>(
"vm-device-id-change",
this._handleDeviceIdChange.bind(this),
);
vm.removeEventListener(
"vm-devices-removed",
this._handleDevicesRemoved.bind(this),
)
});
}
@@ -156,6 +165,13 @@ export const VMDeviceMixin = <T extends Constructor<LitElement>>(
this.deviceSubscriptions.includes("active-ic")
) {
this.updateDevice();
this.requestUpdate();
} else if (this.deviceSubscriptions.includes("visible-devices")) {
const visibleDevices = window.VM.vm.visibleDeviceIds(this.deviceID);
if (visibleDevices.includes(id)) {
this.updateDevice();
this.requestUpdate();
}
}
}
@@ -164,17 +180,39 @@ export const VMDeviceMixin = <T extends Constructor<LitElement>>(
const ids = e.detail;
if (ids.includes(this.deviceID)) {
this.updateDevice();
if (this.deviceSubscriptions.includes("visible-devices")) {
this.requestUpdate();
}
} else if (
ids.includes(activeIcId) &&
this.deviceSubscriptions.includes("active-ic")
) {
this.updateDevice();
this.requestUpdate();
} else if (this.deviceSubscriptions.includes("visible-devices")) {
const visibleDevices = window.VM.vm.visibleDeviceIds(this.deviceID);
if (ids.some( id => visibleDevices.includes(id))) {
this.updateDevice();
this.requestUpdate();
}
}
}
_handleDeviceIdChange(e: CustomEvent<{ old: number; new: number }>) {
if (this.deviceID === e.detail.old) {
this.deviceID = e.detail.new;
} else if (this.deviceSubscriptions.includes("visible-devices")) {
const visibleDevices = window.VM.vm.visibleDeviceIds(this.deviceID);
if (visibleDevices.some(id => id === e.detail.old || id === e.detail.new)) {
this.requestUpdate()
}
}
}
_handleDevicesRemoved(e: CustomEvent<number[]>) {
const _ids = e.detail;
if (this.deviceSubscriptions.includes("visible-devices")) {
this.requestUpdate()
}
}

View File

@@ -8,6 +8,7 @@ import SlInput from "@shoelace-style/shoelace/dist/components/input/input.compon
import SlDialog from "@shoelace-style/shoelace/dist/components/dialog/dialog.component.js";
import "./slot";
import "./fields";
import "./pins";
import { until } from "lit/directives/until.js";
import { repeat } from "lit/directives/repeat.js";
@@ -238,24 +239,12 @@ export class VMDeviceCard extends VMDeviceDBMixin(VMDeviceMixin(BaseElement)) {
}
renderPins() {
const pins = this.pins;
const visibleDevices = window.VM.vm.visibleDevices(this.deviceID);
const pinsHtml = pins?.map(
(pin, index) =>
html`
<sl-select hoist placement="top" clearable key=${index} value=${pin} @sl-change=${this._handleChangePin}>
<span slot="prefix">d${index}</span>
${visibleDevices.map(
(device, _index) =>
html`
<sl-option value=${device.id}>
Device ${device.id} : ${device.name ?? device.prefabName}
</sl-option>
`,
)}
</sl-select>`,
return this.delayRenderTab(
"pins",
html`<div class="pins">
<vm-device-pins .deviceID=${this.deviceID}></vm-device-pins>
</div>`
);
return this.delayRenderTab("pins", html`<div class="pins">${pinsHtml}</div>`);
}
private tabsShown: CardTab[] = ["fields"];
@@ -306,7 +295,7 @@ export class VMDeviceCard extends VMDeviceDBMixin(VMDeviceMixin(BaseElement)) {
<sl-tab slot="nav" panel="slots">Slots</sl-tab>
<sl-tab slot="nav" panel="reagents" disabled>Reagents</sl-tab>
<sl-tab slot="nav" panel="networks">Networks</sl-tab>
<sl-tab slot="nav" panel="pins" ?disabled=${!this.pins}>Pins</sl-tab>
<sl-tab slot="nav" panel="pins" ?disabled=${!this.device.pins}>Pins</sl-tab>
<sl-tab-panel name="fields" active>
${until(this.renderFields(), html`<sl-spinner></sl-spinner>`)}
@@ -320,7 +309,7 @@ export class VMDeviceCard extends VMDeviceDBMixin(VMDeviceMixin(BaseElement)) {
<sl-tab-panel name="networks">
${until(this.renderNetworks(), html`<sl-spinner></sl-spinner>`)}
</sl-tab-panel>
<sl-tab-panel name="pins"> ${this.renderPins()} </sl-tab-panel>
<sl-tab-panel name="pins">${until(this.renderPins(), html`<sl-spinner></sl-spinner>`)} </sl-tab-panel>
</sl-tab-group>
</ic10-details>
<sl-dialog class="remove-device-dialog" no-header @sl-request-close=${this._preventOverlayClose}>
@@ -399,11 +388,4 @@ export class VMDeviceCard extends VMDeviceDBMixin(VMDeviceMixin(BaseElement)) {
this.updateDevice();
}
_handleChangePin(e: CustomEvent) {
const select = e.target as SlSelect;
const pin = parseInt(select.getAttribute("key")!);
const val = select.value ? parseInt(select.value as string) : undefined;
window.VM.get().then((vm) => vm.setDevicePin(this.deviceID, pin, val));
this.updateDevice();
}
}

View File

@@ -0,0 +1,44 @@
import { html, css } from "lit";
import { customElement, property } from "lit/decorators.js";
import { BaseElement, defaultCss } from "components";
import { VMDeviceDBMixin, VMDeviceMixin } from "virtual_machine/base_device";
import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.component.js";
@customElement("vm-device-pins")
export class VMDevicePins extends VMDeviceMixin(VMDeviceDBMixin(BaseElement)) {
constructor() {
super();
this.subscribe("ic", "visible-devices");
}
render() {
const pins = this.pins;
const visibleDevices = window.VM.vm.visibleDevices(this.deviceID);
const pinsHtml = pins?.map(
(pin, index) =>
html`
<sl-select hoist placement="top" clearable key=${index} value=${pin} @sl-change=${this._handleChangePin}>
<span slot="prefix">d${index}</span>
${visibleDevices.map(
(device, _index) =>
html`
<sl-option value=${device.id}>
Device ${device.id} : ${device.name ?? device.prefabName}
</sl-option>
`,
)}
</sl-select>`,
);
return pinsHtml;
}
_handleChangePin(e: CustomEvent) {
const select = e.target as SlSelect;
const pin = parseInt(select.getAttribute("key")!);
const val = select.value ? parseInt(select.value as string) : undefined;
window.VM.get().then((vm) => vm.setDevicePin(this.deviceID, pin, val));
this.updateDevice();
}
}

View File

@@ -119,8 +119,14 @@ class VirtualMachine extends EventTarget {
return ids.map((id, _index) => this._devices.get(id)!);
}
visibleDeviceIds(source: number) {
const ids = Array.from(this.ic10vm.visibleDevices(source));
return ids;
}
updateDevices() {
var update_flag = false;
const removedDevices = [];
const device_ids = this.ic10vm.devices;
for (const id of device_ids) {
if (!this._devices.has(id)) {
@@ -132,6 +138,7 @@ class VirtualMachine extends EventTarget {
if (!device_ids.includes(id)) {
this._devices.delete(id);
update_flag = true;
removedDevices.push(id);
}
}
@@ -160,6 +167,13 @@ class VirtualMachine extends EventTarget {
detail: ids,
}),
);
if (removedDevices.length > 0) {
this.dispatchEvent(
new CustomEvent("vm-devices-removed", {
detail: removedDevices,
}),
);
}
this.app.session.save();
}
}