logicsimulator/components/led.ts

119 lines
3.8 KiB
TypeScript

// Single LED component for the LogicSimulator
// Copyright (C) 2022 Sascha Nitsch
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
interface LEDParam extends BaseComponentParam {
color: string;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class LED extends BaseComponent {
private color: string;
private onColor: string;
private offColor: string;
private a: boolean | null = false;
private b: boolean | null = false;
constructor(simulator: Simulator, id: string, param: LEDParam) {
super(simulator, id, param);
this.color = param.color;
switch (this.color) {
case 'red':
this.onColor = 'ffb9b9';
this.offColor = '990000';
break;
case 'blue':
this.onColor = 'b9b9ff';
this.offColor = '2222ff';
break;
case 'green':
this.onColor = 'b9ffb9';
this.offColor = '22b922';
break;
case 'orange':
this.onColor = 'ff9900';
this.offColor = 'cc5500';
break;
case 'yellow':
this.onColor = 'ffffb9';
this.offColor = 'cccc00';
break;
default:
this.onColor = 'ffffff';
this.offColor = '444444';
}
this.pins.set(
'a',
new TriState(this, 0, -10, undefined, {
type: 'LED',
id: id + '-a',
})
);
this.pins.set(
'b',
new TriState(this, 0, 10, undefined, {
type: 'LED',
id: id + '-b',
})
);
}
addGradient(canvas: SVGElement, type: string, color1: string, color2: string) {
const grad = document.createElementNS('http://www.w3.org/2000/svg', 'radialGradient');
grad.id = 'radialGradient' + type + this.color;
let stop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');
stop.setAttribute('offset', '0.4');
stop.setAttribute('style', 'stop-color:#' + color1 + ';stop-opacity:1');
grad.appendChild(stop);
stop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');
stop.setAttribute('offset', '1');
stop.setAttribute('style', 'stop-color:#' + color2 + ';stop-opacity:1');
grad.appendChild(stop);
canvas.appendChild(grad);
}
setup(parent: SVGElement) {
// color already registered?
const canvas = parent.ownerSVGElement;
if (canvas === null) return;
const c = canvas.getElementById('radialGradientOff' + this.color);
if (c === null) {
this.addGradient(canvas, 'Off', this.offColor, this.offColor);
this.addGradient(canvas, 'On', this.onColor, this.offColor);
}
super.doSetup('led', parent);
if (this.element) {
this.element.setAttribute('style', 'fill:url(#radialGradientOff' + this.color + ')');
}
}
io() {
this.a = this.tri(this.getPin('a').getAndReset());
this.b = this.tri(this.getPin('b').getAndReset());
}
update() {
const stateA = this.a;
const stateB = this.b;
if (this.element !== null) {
if (stateA !== stateB && stateA !== null && stateB !== null) {
this.element.setAttribute('style', 'fill:url(#radialGradientOn' + this.color + ')');
} else {
this.element.setAttribute('style', 'fill:url(#radialGradientOff' + this.color + ')');
}
}
return false;
}
}