logicsimulator/components/togglebutton.ts

153 lines
5.3 KiB
TypeScript

// Toggle-button 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/>.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class ToggleButton extends BaseComponent {
private pressed = false;
private forcephysical = false;
private text: NodeListOf<Element> | undefined;
private a: WireState;
private q: WireState;
private p1: WireState;
private p2: WireState;
private p3: WireState;
private p4: WireState;
constructor(simulator: Simulator, id: string, param: BaseComponentParam) {
super(simulator, id, param);
this.pins.set('a', new TriState(this, 0, 0, undefined, { id: id + '-a' }));
this.pins.set('q', new TriState(this, 0, 0, undefined, { id: id + '-q' }));
this.pins.set('p1', new TriState(this, 0, 0, undefined, { id: id + '-p1' }));
this.pins.set('p2', new TriState(this, 10.16, 0, undefined, { id: id + '-p2' }));
this.pins.set(
'p3',
new TriState(this, 10.16, -5.08 * 3, undefined, {
id: id + '-p3',
})
);
this.pins.set('p4', new TriState(this, 0, -5.08 * 3));
if (this.extraclass && this.extraclass.indexOf('forcephysical') !== -1) {
this.forcephysical = true;
}
this.a = WireState.float;
this.q = WireState.float;
this.p1 = WireState.float;
this.p2 = WireState.float;
this.p3 = WireState.float;
this.p4 = WireState.float;
}
setup(canvas: SVGElement) {
super.doSetup('togglebutton', canvas);
if (this.element !== null) {
this.text = this.element.querySelectorAll('.inner');
this.element.addEventListener('mousedown', this.activate.bind(this));
}
if (this.breadboard) {
this.simulator.wire(null, [this.getPin('p1'), this.breadboard.getPin('E' + this.col)]);
this.simulator.wire(null, [this.getPin('p2'), this.breadboard.getPin('E' + (2 + this.col))]);
this.simulator.wire(null, [this.getPin('p3'), this.breadboard.getPin('F' + (2 + this.col))]);
this.simulator.wire(null, [this.getPin('p4'), this.breadboard.getPin('F' + this.col)]);
}
}
activate(e: Event) {
// console.log(e);
e.preventDefault();
this.pressed = !this.pressed;
// document.text = this.text;
if (this.breadboard || this.forcephysical) {
if (this.text !== undefined) {
this.text[1].textContent = this.pressed ? '1' : '0';
}
} else {
if (this.text !== undefined) {
this.text[0].textContent = this.pressed ? '---' : '] [';
}
}
this.simulator.manualtick();
}
io() {
this.a = this.getPin('a').getAndReset();
this.p1 = this.getPin('p1').getAndReset();
this.p2 = this.getPin('p2').getAndReset();
this.p3 = this.getPin('p3').getAndReset();
this.p4 = this.getPin('p4').getAndReset();
// console.log(this.id, "input:", this.state.p1, this.state.p4);
}
update() {
if (this.breadboard || this.forcephysical) {
let top = this.p3;
if (top !== WireState.float) {
if (this.p4 !== WireState.float && this.p4 !== top) {
console.log('boom ToggleButton top', this.id);
}
} else {
top = this.p4;
}
const bottom = this.p1;
if (bottom !== WireState.float) {
if (this.p2 !== WireState.float && this.p2 !== bottom) {
console.log('boom ToggleButton buttom', this.id);
}
} else {
top = this.p2;
}
if (this.pressed) {
let mod = false;
if (top === WireState.float || top === WireState.up || top === WireState.down) {
const old = top;
this.p3 = bottom;
this.p4 = bottom;
this.getPin('p3').setState(bottom);
this.getPin('p4').setState(bottom);
mod = bottom !== old;
} else if (bottom === WireState.float || bottom === WireState.up || bottom === WireState.down) {
const old = bottom;
this.p1 = top;
this.p2 = top;
this.getPin('p1').setState(top);
this.getPin('p2').setState(top);
mod = top !== <WireState>old;
} else {
if (top === bottom) {
this.p1 = top;
this.p2 = top;
this.p3 = top;
this.p4 = top;
this.getPin('p1').setState(top);
this.getPin('p2').setState(top);
this.getPin('p3').setState(top);
this.getPin('p4').setState(top);
} else {
console.log('boom togglebutton', this.id, top, bottom);
}
}
return mod;
} else {
return false;
}
} else {
const oldstate = this.q;
const q = this.pressed ? this.a : WireState.float;
this.q = q;
this.getPin('q').setState(q);
return oldstate !== q;
}
}
}