From af5fc0c4fc45f104f8a54fcd9021b2871bd9af75 Mon Sep 17 00:00:00 2001 From: Guy Perfect Date: Fri, 3 Sep 2021 17:38:48 +0000 Subject: [PATCH] Tweaks from concurrent project --- app/App.js | 1 - app/theme/kiosk.css | 25 ++++ app/toolkit/ListBox.js | 234 ++++++++++++++++++++++++++++++++++++ app/toolkit/Panel.js | 5 + app/windows/CPUWindow.js | 16 ++- app/windows/MemoryWindow.js | 14 +-- app/windows/Register.js | 6 +- 7 files changed, 283 insertions(+), 18 deletions(-) create mode 100644 app/toolkit/ListBox.js diff --git a/app/App.js b/app/App.js index c1f58ed..0df8cfd 100644 --- a/app/App.js +++ b/app/App.js @@ -121,7 +121,6 @@ globalThis.App = class App { // ROM buffer has been configured setROM(msg) { let dbg = this.debuggers[msg.sim]; - dbg.memory.setVisible(true, true); dbg.refresh(); } diff --git a/app/theme/kiosk.css b/app/theme/kiosk.css index 8691fe6..91a63b2 100644 --- a/app/theme/kiosk.css +++ b/app/theme/kiosk.css @@ -167,6 +167,20 @@ body { +/********************************** ListBox **********************************/ + +select { + background : var(--window); + border : 1px solid var(--control-shadow); + color : var(--window-text); + font-family: var(--font-dialog); + font-size : var(--font-size); + line-height: var(--font-size); + padding : 1px; +} + + + /********************************** MenuBar **********************************/ [role="menubar"] { @@ -230,8 +244,10 @@ input[type="text"] { background : var(--window); border : 1px solid var(--control-shadow); color : var(--window-text); + font-family: var(--font-dialog); font-size : var(--font-size); line-height: var(--font-size); + padding : 1px; } @@ -418,7 +434,9 @@ input[type="text"] { [role="dialog"][window="cpu"] [name="wrap-registers"] input[type="text"] { border : none; font-family : var(--font-hex); + height : var(--font-size); margin-right: 1px; + padding : 0; text-align : right; width : 58px; } @@ -474,3 +492,10 @@ input[type="text"] { border-color: var(--control-shadow); color : var(--window-text); } + +[role="dialog"][window="cpu"] [name="expansion"] + input[type="text"][aria-disabled="true"], +[role="dialog"][window="cpu"] [name="expansion"] + [aria-disabled="true"] [name="check"]{ + cursor: not-allowed !important; +} diff --git a/app/toolkit/ListBox.js b/app/toolkit/ListBox.js new file mode 100644 index 0000000..6f205b9 --- /dev/null +++ b/app/toolkit/ListBox.js @@ -0,0 +1,234 @@ +"use strict"; + +// Multi-item list picker +Toolkit.ListBox = class ListBox extends Toolkit.Component { + + // Object constructor + constructor(application, options) { + super(application, "select", options); + options = options || {}; + + // Configure instance fields + this.changeListeners = []; + this.dropDown = true; + this.enabled = "enabled" in options ? !!options.enabled : true; + this.items = []; + this.name = options.name || ""; + + // Configure element + this.element.addEventListener("input", e=>this.onchange(e)); + + // Configure properties + this.setDropDown(this.dropDown); + this.setEnabled (this.enabled ); + this.setName (this.name ); + if ("items" in options) + this.add(options.items); + this.application.addComponent(this); + } + + + + ///////////////////////////// Public Methods ////////////////////////////// + + // Add one or more items to the list box + add(items, offset, count) { + + // Configure arguments + if (!Array.isArray(items)) + items = [ items ]; + offset = offset || 0; + if (offset < 0 || offset >= items.length) + return; + count = count || items.length - offset; + if (count < 1) + return; + count = Math.min(count, items.length - offset) + + // Add the items to the list + for (let x = 0; x < count; x++) { + let item = items[offset + x]; + let option = new Toolkit.ListBox.Option(this.application, item); + this.items.push(option); + this.element.appendChild(option.element); + } + + } + + // Add a callback for chabge events + addChangeListener(listener) { + if (this.changeListeners.indexOf(listener) == -1) + this.changeListeners.push(listener); + } + + // Remove all items from the list + clear() { + for (let item of this.items) + this.remove(item); + this.items.splice(0, this.items.length); + } + + // Request focus on the appropriate element + focus() { + this.element.focus(); + } + + // Retrieve the component's accessible name + getName() { + return this.name; + } + + // Retrieve the index of the currently selected item + getSelectedIndex() { + return this.element.selectedIndex; + } + + // Retrieve the currently selected item + getSelectedItem() { + let index = this.element.selectedIndex; + return index == -1 ? null : this.items[index]; + } + + // Retrieve the value of the currently selected item + getValue() { + let item = this.getSelectedItem(); + return item == null ? null : item.getValue(); + } + + // Determine whether the component is a drop-down list + isDropDown() { + return this.dropDown; + } + + // Determine whether the component is enabled + isEnabled() { + return this.enabled; + } + + // Remove an item from the list + remove(item, delocalize) { + let index = this.items.indexOf(item); + + // Error checking + if (index == -1) + return; + + // Remove the element + item.element.remove(); + this.items.splice(index, 1); + + // De-localize the element + if (delocalize === undefined || delocalize) + item.application.removeComponent(item); + } + + // Specify whether the component is a drop-down list + setDropDown(dropDown) { + // Not yet implemented + } + + // Specify whether the component is enabled + setEnabled(enabled) { + this.enabled = enabled = !!enabled; + this.element.setAttribute("aria-disabled", !enabled); + } + + // Specify the component's accessible name + setName(name) { + this.name = name || ""; + this.localize(); + } + + // Specify the index of the selected item + setSelectedIndex(index) { + if (typeof index != "number") + return element.selectedIndex; + index = Math.max(Math.min(Math.trunc(index), this.items.length-1), -1); + this.element.selectedIndex = index; + return index; + } + + + + ///////////////////////////// Package Methods ///////////////////////////// + + // Update display text with localized strings + localize() { + let name = this.name; + if (this.application) + name = this.application.translate(name, this); + this.element.setAttribute("aria-label", name); + } + + + + ///////////////////////////// Private Methods ///////////////////////////// + + // Selection changed event handler + onchange(e) { + if (!this.enabled) + return; + for (let listener of this.changeListeners) + listener(e); + } + +}; + +// List box item +Toolkit.ListBox.Option = class Option extends Toolkit.Component { + + // Object constructor + constructor(application, options) { + super(application, "option", options); + options = options || {}; + + // Configure instance fields + this.localized = "localized" in options ? !!options.localized : true; + this.text = options.text || ""; + this.value = options.value || null; + + // Configure properties + this.setText (this.text ); + this.setValue(this.value); + if (this.localized) + this.application.addComponent(this); + } + + + + ///////////////////////////// Public Methods ////////////////////////////// + + // Retrieve the component's display text + getText() { + return this.text; + } + + // Retrieve the component's value + getValue() { + return this.value; + } + + // Specify the component's display text + setText(text) { + this.text = text || ""; + this.localize(); + } + + // Specify the component's value + setValue(value) { + this.value = value; + } + + + + ///////////////////////////// Package Methods ///////////////////////////// + + // Update display text with localized strings + localize() { + let text = this.text; + if (this.localized && this.application) + text = this.application.translate(text, this); + this.element.innerText = text; + } + +}; diff --git a/app/toolkit/Panel.js b/app/toolkit/Panel.js index 4ea24ff..f8486bf 100644 --- a/app/toolkit/Panel.js +++ b/app/toolkit/Panel.js @@ -91,6 +91,11 @@ Toolkit.Panel = class Panel extends Toolkit.Component { return new Toolkit.Label(this.application, options); } + // Create a ListBox and associate it with the application + newListBox(options) { + return new Toolkit.ListBox(this.application, options); + } + // Create a MenuBar and associate it with the application newMenuBar(options) { return new Toolkit.MenuBar(this.application, options); diff --git a/app/windows/CPUWindow.js b/app/windows/CPUWindow.js index 3cae9be..58f00a2 100644 --- a/app/windows/CPUWindow.js +++ b/app/windows/CPUWindow.js @@ -218,13 +218,17 @@ // Update the display with current emulation data refresh(clientHeight, lineHeight, registers) { - if (!registers) { - this.debug.core.postMessage({ - command: "GetRegisters", - debug : "CPU", - sim : this.debug.sim - }); + if (!this.isVisible()) + return; + if (registers) { + this.getRegisters({ registers }); + return; } + this.debug.core.postMessage({ + command: "GetRegisters", + debug : "CPU", + sim : this.debug.sim + }); } diff --git a/app/windows/MemoryWindow.js b/app/windows/MemoryWindow.js index 7158624..865ef86 100644 --- a/app/windows/MemoryWindow.js +++ b/app/windows/MemoryWindow.js @@ -106,7 +106,7 @@ globalThis.MemoryWindow = class MemoryWindow extends Toolkit.Window { for ( let x = 0, address = this.address, offset = 0; x < this.rows.length && offset < bytes.length; - x++, address = (address + 16 & 0xFFFFFFFF) >>> 0, offset += 16 + x++, address = (address + 16 & 0xFFFFFFF0) >>> 0, offset += 16 ) this.rows[x].update(address, bytes, offset); } @@ -155,21 +155,21 @@ globalThis.MemoryWindow = class MemoryWindow extends Toolkit.Window { // Processing by key else switch (e.key) { case "ArrowDown": - this.address = (this.address + 16 & 0xFFFFFFFF) >>> 0; + this.address = (this.address + 16 & 0xFFFFFFF0) >>> 0; this.refresh(); break; case "ArrowUp": - this.address = (this.address - 16 & 0xFFFFFFFF) >>> 0; + this.address = (this.address - 16 & 0xFFFFFFF0) >>> 0; this.refresh(); break; case "PageUp": this.address = (this.address - 16 * this.lines(true) & - 0xFFFFFFFF) >>> 0; + 0xFFFFFFF0) >>> 0; this.refresh(); break; case "PageDown": this.address = (this.address + 16 * this.lines(true) & - 0xFFFFFFFF) >>> 0; + 0xFFFFFFF0) >>> 0; this.refresh(); break; default: return super.onkeydown(e); @@ -193,13 +193,13 @@ globalThis.MemoryWindow = class MemoryWindow extends Toolkit.Window { e.stopPropagation(); // Specify the new address - this.address = (this.address + sign * mag * 16 & 0xFFFFFFFF) >>> 0; + this.address = (this.address + sign * mag * 16 & 0xFFFFFFF0) >>> 0; this.refresh(null, lineHeight); } // Move to a new address positioned at a particular row of output seek(address, index) { - this.address = (address - (index || 0) * 16 & 0xFFFFFFFF) >>> 0; + this.address = (address - (index || 0) * 16 & 0xFFFFFFF0) >>> 0; } }; diff --git a/app/windows/Register.js b/app/windows/Register.js index 5b33c76..567f528 100644 --- a/app/windows/Register.js +++ b/app/windows/Register.js @@ -312,8 +312,7 @@ localized: true, text : "{cpu.pcFrom}" })); - lbl.element.setAttribute("name", "indent"); - this.txtFrom = this.expansion.add(this.newTextBox()); + this.txtFrom = this.expansion.add(this.newTextBox({ enabled: false })); this.txtFrom.element.setAttribute("name", "value"); // To text box @@ -321,8 +320,7 @@ localized: true, text : "{cpu.pcTo}" })); - lbl.element.setAttribute("name", "indent"); - this.txtTo = this.expansion.add(this.newTextBox()); + this.txtTo = this.expansion.add(this.newTextBox({ enabled: false })); this.txtTo.element.setAttribute("name", "value"); }