Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor led renderers #17

Merged
merged 1 commit into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
<led-register-table rega="0" regb="0" id="registers-table"></led-register-table>

<p class="title-text">Memory</p>
<led-table class="ledTable" color="red" id="memory-table"></led-table>
<led-memory-table class="ledTable" color="red" id="memory-table"></led-memory-table>
</card-component>

<card-component class="editor-card" title="S.M.A.R.T Assembly Code Editor" width="5" height="19" id="editor-card" href="https://github.com/yaacov/smart-tools">
Expand Down
2 changes: 1 addition & 1 deletion public/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import compile from './src/compiler.mjs';
// Virtual machine
const memorySize = 256;
const vm = new VM(memorySize);
const runningStepTimeMs = 100;
const runningStepTimeMs = 50;

let runningSteps = 0;
let runningInterval;
Expand Down
2 changes: 1 addition & 1 deletion public/js/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import './led-indicator.js';
import './led-switch.js';
import './led-array.js';
import './led-switch-array.js';
import './led-table.js';
import './led-memory-table.js';
import './led-register-table.js';
import './code-editor.js';
import './hex-value.js';
Expand Down
55 changes: 34 additions & 21 deletions public/js/components/led-array.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { html } from '../html.js';

/* eslint-disable no-underscore-dangle */
class LedArray extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this._value = null;
this._ledIndicators = [];
this._width = parseInt(this.getAttribute('width') || '8', 10);
this._color = this.getAttribute('color') || 'green';
}

connectedCallback() {
Expand All @@ -14,30 +17,40 @@ class LedArray extends HTMLElement {
return ['value'];
}

attributeChangedCallback(name) {
if (name === 'value') {
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'value' && oldValue !== newValue) {
this._value = newValue;
this.render();
}
}

render() {
const width = parseInt(this.getAttribute('width') || '8', 10);
const color = this.getAttribute('color') || 'green';
const value = parseInt(this.getAttribute('value'), 10) || 0;
const binaryString = value.toString(2).padStart(width, '0');

this.shadowRoot.innerHTML = html`
<style>
.led-container {
display: flex;
align-items: center;
gap: 5px;
}
</style>
<div class="led-container">
${binaryString.split('').map((bit) => `<led-indicator color="${color}" value="${bit === '1'}"></led-indicator>`).join('')}
</div>
`;
const value = parseInt(this._value, 10) || 0;
const binaryString = value.toString(2).padStart(this._width, '0');

// Create the led-container if it doesn't exist
let ledContainer = this.shadowRoot.querySelector('.led-container');
if (!ledContainer) {
ledContainer = document.createElement('div');
ledContainer.className = 'led-container';
this.shadowRoot.appendChild(ledContainer);
ledContainer.style.display = 'flex';
ledContainer.style.alignItems = 'center';
ledContainer.style.gap = '5px';
}

// Update or create led-indicator elements
binaryString.split('').forEach((bit, index) => {
let ledIndicator = this._ledIndicators[index];
if (!ledIndicator) {
ledIndicator = document.createElement('led-indicator');
this._ledIndicators[index] = ledIndicator;

ledContainer.appendChild(ledIndicator);
ledIndicator.setAttribute('color', this._color);
}
ledIndicator.setAttribute('value', bit === '1');
});
}
}

Expand Down
136 changes: 136 additions & 0 deletions public/js/components/led-memory-table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/* eslint-disable class-methods-use-this */
/* eslint-disable no-underscore-dangle */
/* eslint-disable no-restricted-syntax */
import { html } from '../html.js';

class LedMemoryTable extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this._indexesToRender = [];

this._prevValueArray = null;
this._prevIndicatorArray = null;

this._data = JSON.parse(this.getAttribute('data') || '[]');

this._tableElement = document.createElement('table');
this.shadowRoot.appendChild(this._tableElement);

this._style = document.createElement('style');
this._style.innerHTML = html`
table {
border-collapse: collapse;
}
td {
padding: 2px 6px;
text-align: left;
font-weight: bold;
}
.address {
cursor: pointer;
}
.address:hover {
color: #f0f0f0;
}
.label {
color: #D4AF37;
}
.decimal {
color: #D3D3D3;
}
`;
this.shadowRoot.appendChild(this._style);
}

buildArrays(data) {
return data.reduce((acc, item) => {
acc[0].push(item.value);
acc[1].push(item.indicator);
return acc;
}, [[], []]);
}

connectedCallback() {
this.render();
}

static get observedAttributes() {
return ['data'];
}

attributeChangedCallback(name, oldValue, newValue) {
if (name === 'data' && oldValue !== newValue) {
const newData = JSON.parse(newValue || '[]');
this._indexesToRender = this.getIndexesToRender(newData);

if (this._indexesToRender.length > 0 || this._data.length !== newData.length) {
[this._prevValueArray, this._prevIndicatorArray] = this.buildArrays(newData);
this._data = newData;

this.render();
}
}
}

getIndexesToRender(newData) {
const indexesToRender = [];

if (!this._data) {
for (let i = 0; i < newData.length; i++) {
indexesToRender.push(i);
}
} else {
const newLength = newData.length;
const prevLength = this._data.length;

for (let i = 0; i < newLength; i++) {
if (!this._prevIndicatorArray || newData[i].indicator !== this._prevIndicatorArray[i] || newData[i].value !== this._prevValueArray[i]) {
indexesToRender.push(i);
}
}

// If the new data is shorter, add all remaining indexes from the old data
if (newLength < prevLength) {
for (let i = newLength; i < prevLength; i++) {
indexesToRender.push(i);
}
}
}

return indexesToRender;
}

render() {
const table = this._tableElement;

for (const i of this._indexesToRender) {
const item = this._data[i];
let row = table.rows[i];

if (!row) {
row = table.insertRow();
}

row.innerHTML = this.getRowStaticContent(item);
}
}

getRowStaticContent(item) {
const address = `0x${item.address.toString(16).toUpperCase().padStart(2, '0')}`;
const valueHex = `0x${item.value.toString(16).toUpperCase().padStart(2, '0')}`;
const valueDecimal = `${item.value.toString(10).padStart(3, '0')}`;

return html`
<td class="address">${address}</td>
<td><led-array color="red" width="1" value="${item.indicator ? '1' : '0'}"></led-array>
<td><led-array color="green" width="8" value="${item.value}"></led-array></td>
<td>${valueHex}</td>
<td class="label">${item.label || ''}</td>
${item.opCode ? `<td>${item.opCode}</td>` : `<td class="decimal">${item.oprand || ''}</td>`}
<td class="decimal">${valueDecimal}</td>
`;
}
}

customElements.define('led-memory-table', LedMemoryTable);
91 changes: 0 additions & 91 deletions public/js/components/led-table.js

This file was deleted.