Cleaned up how components print messages and how the Computer component overrides their notice/print/println methods (in preparation for new Computer overrides)

This commit is contained in:
Jeff Parsons 2017-06-28 10:53:44 -07:00 committed by Jeff Parsons
commit d4d3448fd5
20 changed files with 954 additions and 910 deletions

View file

@ -325,14 +325,15 @@ class C1PComputer extends Component {
/*
* Iterate through all the other components and update their print methods if the Control Panel has provided overrides.
*/
if (panel.controlPrint) {
var controlPrint = panel.bindings['print'];
if (controlPrint) {
var aComponents = Component.getComponents(parmsComputer['id']);
for (var iComponent = 0; iComponent < aComponents.length; iComponent++) {
component = aComponents[iComponent];
if (component == panel) continue;
component.notice = panel.notice;
component.print = panel.print;
component.println = panel.println;
component.controlPrint = panel.controlPrint;
}
}
}

View file

@ -177,9 +177,11 @@ class Computer8080 extends Component {
*/
var iComponent, component;
var aComponents = Component.getComponents(this.id);
this.panel = /** @type {Panel8080} */ (Component.getComponentByType("Panel", this.id));
if (this.panel && this.panel.controlPrint) {
this.panel = /** @type {Panel8080} */ (Component.getComponentByType("Panel", this.id));
this.controlPrint = this.panel && this.panel.bindings['print'];
if (this.controlPrint) {
for (iComponent = 0; iComponent < aComponents.length; iComponent++) {
component = aComponents[iComponent];
/*
@ -188,8 +190,8 @@ class Computer8080 extends Component {
* too darn convenient to slam those overrides into the components directly.
*/
component.notice = this.panel.notice;
component.print = this.panel.print;
component.println = this.panel.println;
component.controlPrint = this.panel.controlPrint;
}
}
@ -277,6 +279,18 @@ class Computer8080 extends Component {
if (!fSuspended && this.fAutoPower) this.wait(this.powerOn);
}
/**
* clearPanel()
*
* @this {Computer8080}
*/
clearPanel()
{
if (this.controlPrint) {
this.controlPrint.value = "";
}
}
/**
* getMachineID()
*

View file

@ -229,15 +229,6 @@ class CPU8080 extends Component {
if (DEBUGGER && this.dbg) {
this.dbg.init();
} else {
/*
* The Computer (this.cmp) knows if there's a Control Panel (this.cmp.panel), and the Control Panel
* knows if there's a "print" control (this.cmp.panel.controlPrint), and if there IS a "print" control
* but no debugger, the machine is probably misconfigured (most likely, the page simply neglected to
* load the Debugger component).
*
* However, we don't actually need to check all that; it's always safe use println(), regardless whether
* a Control Panel with a "print" control is present or not.
*/
this.println("No debugger detected");
}
}

View file

@ -2566,10 +2566,7 @@ class Debugger8080 extends Debugger {
*/
doClear(sCmd)
{
/*
* TODO: There should be a clear() component method that the Control Panel overrides to perform this function.
*/
if (this.controlPrint) this.controlPrint.value = "";
this.cmp.clearPanel();
}
/**

View file

@ -341,11 +341,7 @@ class RAM8080 extends Component {
*/
writeCPMString(s)
{
s = s.replace(/\r/g, '');
if (this.controlPrint) {
this.controlPrint.value += s;
this.controlPrint.scrollTop = this.controlPrint.scrollHeight;
}
this.print(s.replace(/\r/g, ''));
}
/**

View file

@ -202,13 +202,16 @@ class Computer extends Component {
this.bus = new Bus({'id': this.idMachine + '.bus', 'busWidth': this.nBusWidth}, this.cpu, this.dbg);
/*
* Iterate through all the components and connect them to the Control Panel, if any
* Iterate through all the components and override their notice() and println() methods so that their
* output can be rerouted to an Initialization Display or a Control Panel, if any.
*/
var iComponent, component;
var aComponents = Component.getComponents(this.id);
this.panel = /** @type {Panel} */ (Component.getComponentByType("Panel", this.id));
if (this.panel && this.panel.controlPrint) {
this.panel = /** @type {Panel} */ (Component.getComponentByType("Panel", this.id));
this.controlPrint = this.panel && this.panel.bindings['print'];
if (this.controlPrint) {
for (iComponent = 0; iComponent < aComponents.length; iComponent++) {
component = aComponents[iComponent];
/*
@ -217,8 +220,8 @@ class Computer extends Component {
* too darn convenient to slam those overrides into the components directly.
*/
component.notice = this.panel.notice;
component.print = this.panel.print;
component.println = this.panel.println;
component.controlPrint = this.panel.controlPrint;
}
}
@ -309,6 +312,18 @@ class Computer extends Component {
if (!fSuspended && this.fAutoPower) this.wait(this.powerOn);
}
/**
* clearPanel()
*
* @this {Computer}
*/
clearPanel()
{
if (this.controlPrint) {
this.controlPrint.value = "";
}
}
/**
* getMachineID()
*

View file

@ -234,15 +234,6 @@ class CPU extends Component {
if (DEBUGGER && this.dbg) {
this.dbg.init();
} else {
/*
* The Computer (this.cmp) knows if there's a Control Panel (this.cmp.panel), and the Control Panel
* knows if there's a "print" control (this.cmp.panel.controlPrint), and if there IS a "print" control
* but no debugger, the machine is probably misconfigured (most likely, the page simply neglected to
* load the Debugger component).
*
* However, we don't actually need to check all that; it's always safe use println(), regardless whether
* a Control Panel with a "print" control is present or not.
*/
this.println("No debugger detected");
}
}

View file

@ -4755,10 +4755,7 @@ class DebuggerX86 extends Debugger {
*/
doClear(sCmd)
{
/*
* TODO: There should be a clear() component method that the Control Panel overrides to perform this function.
*/
if (this.controlPrint) this.controlPrint.value = "";
this.cmp.clearPanel();
}
/**

View file

@ -98,6 +98,7 @@ class ComputerPDP10 extends Component {
* function (if it has one--it's optional). We call the CPU's powerUp() function last,
* so that the CPU is assured that all other components are ready and "powered".
*
* @this {ComputerPDP10}
* @param {Object} parmsComputer
* @param {Object} [parmsMachine]
* @param {boolean} [fSuspended]
@ -164,9 +165,11 @@ class ComputerPDP10 extends Component {
*/
var iComponent, component;
var aComponents = Component.getComponents(this.id);
this.panel = /** @type {PanelPDP10} */ (Component.getComponentByType("Panel", this.id));
if (this.panel && this.panel.controlPrint) {
this.panel = /** @type {PanelPDP10} */ (Component.getComponentByType("Panel", this.id));
this.controlPrint = this.panel && this.panel.bindings['print'];
if (this.controlPrint) {
for (iComponent = 0; iComponent < aComponents.length; iComponent++) {
component = aComponents[iComponent];
/*
@ -175,8 +178,8 @@ class ComputerPDP10 extends Component {
* too darn convenient to slam those overrides into the components directly.
*/
component.notice = this.panel.notice;
component.print = this.panel.print;
component.println = this.panel.println;
component.controlPrint = this.panel.controlPrint;
}
}
@ -262,9 +265,22 @@ class ComputerPDP10 extends Component {
if (!fSuspended && this.fAutoPower) this.wait(this.powerOn);
}
/**
* clearPanel()
*
* @this {ComputerPDP10}
*/
clearPanel()
{
if (this.controlPrint) {
this.controlPrint.value = "";
}
}
/**
* getMachineID()
*
* @this {ComputerPDP10}
* @return {string}
*/
getMachineID()
@ -277,6 +293,7 @@ class ComputerPDP10 extends Component {
*
* If no explicit machine parms were provided, then we check for 'parms' in the bundled resources (if any).
*
* @this {ComputerPDP10}
* @param {Object} [parmsMachine]
*/
setMachineParms(parmsMachine)
@ -308,6 +325,7 @@ class ComputerPDP10 extends Component {
* (eg, Str.TYPES.NUMBER) is used, the return value will be that type; unfortunately, every caller
* must coerce their own return value.
*
* @this {ComputerPDP10}
* @param {string} sParm
* @param {Object|null} [parmsComponent]
* @param {number} [type] (from Str.TYPES)
@ -345,6 +363,7 @@ class ComputerPDP10 extends Component {
/**
* saveMachineParms()
*
* @this {ComputerPDP10}
* @return {string|null}
*/
saveMachineParms()
@ -355,6 +374,7 @@ class ComputerPDP10 extends Component {
/**
* getUserID()
*
* @this {ComputerPDP10}
* @return {string}
*/
getUserID()
@ -1161,6 +1181,8 @@ class ComputerPDP10 extends Component {
/**
* resetUserID()
*
* @this {ComputerPDP10}
*/
resetUserID()
{
@ -1171,6 +1193,7 @@ class ComputerPDP10 extends Component {
/**
* queryUserID(fPrompt)
*
* @this {ComputerPDP10}
* @param {boolean} [fPrompt]
* @returns {string|null|undefined}
*/
@ -1259,6 +1282,7 @@ class ComputerPDP10 extends Component {
/**
* saveServerState(sUserID, sState)
*
* @this {ComputerPDP10}
* @param {string} sUserID
* @param {string|null} sState
*/

View file

@ -232,15 +232,6 @@ class CPUPDP10 extends Component {
if (DEBUGGER && this.dbg) {
this.dbg.init(this.flags.autoStart);
} else {
/*
* The Computer (this.cmp) knows if there's a Control Panel (this.panel), and the Control Panel
* knows if there's a "print" control (this.panel.controlPrint), and if there IS a "print" control
* but no debugger, the machine is probably misconfigured (most likely, the page simply neglected to
* load the Debugger component).
*
* However, we don't actually need to check all that; it's always safe use println(), regardless whether
* a Control Panel with a "print" control is present or not.
*/
this.status("No debugger detected");
}
if (!this.flags.autoStart) {

View file

@ -2848,10 +2848,7 @@ class DebuggerPDP10 extends Debugger {
*/
doClear(sCmd)
{
/*
* TODO: There should be a clear() component method that the Control Panel overrides to perform this function.
*/
if (this.controlPrint) this.controlPrint.value = "";
this.cmp.clearPanel();
}
/**

View file

@ -98,6 +98,7 @@ class ComputerPDP11 extends Component {
* function (if it has one--it's optional). We call the CPU's powerUp() function last,
* so that the CPU is assured that all other components are ready and "powered".
*
* @this {ComputerPDP11}
* @param {Object} parmsComputer
* @param {Object} [parmsMachine]
* @param {boolean} [fSuspended]
@ -164,9 +165,11 @@ class ComputerPDP11 extends Component {
*/
var iComponent, component;
var aComponents = Component.getComponents(this.id);
this.panel = /** @type {PanelPDP11} */ (Component.getComponentByType("Panel", this.id));
if (this.panel && this.panel.controlPrint) {
this.panel = /** @type {PanelPDP11} */ (Component.getComponentByType("Panel", this.id));
this.controlPrint = this.panel && this.panel.bindings['print'];
if (this.controlPrint) {
for (iComponent = 0; iComponent < aComponents.length; iComponent++) {
component = aComponents[iComponent];
/*
@ -175,8 +178,8 @@ class ComputerPDP11 extends Component {
* too darn convenient to slam those overrides into the components directly.
*/
component.notice = this.panel.notice;
component.print = this.panel.print;
component.println = this.panel.println;
component.controlPrint = this.panel.controlPrint;
}
}
@ -266,9 +269,22 @@ class ComputerPDP11 extends Component {
if (!fSuspended && this.fAutoPower) this.wait(this.powerOn);
}
/**
* clearPanel()
*
* @this {ComputerPDP11}
*/
clearPanel()
{
if (this.controlPrint) {
this.controlPrint.value = "";
}
}
/**
* getMachineID()
*
* @this {ComputerPDP11}
* @return {string}
*/
getMachineID()
@ -281,6 +297,7 @@ class ComputerPDP11 extends Component {
*
* If no explicit machine parms were provided, then we check for 'parms' in the bundled resources (if any).
*
* @this {ComputerPDP11}
* @param {Object} [parmsMachine]
*/
setMachineParms(parmsMachine)
@ -312,6 +329,7 @@ class ComputerPDP11 extends Component {
* (eg, Str.TYPES.NUMBER) is used, the return value will be that type; unfortunately, every caller
* must coerce their own return value.
*
* @this {ComputerPDP11}
* @param {string} sParm
* @param {Object|null} [parmsComponent]
* @param {number} [type] (from Str.TYPES)
@ -349,6 +367,7 @@ class ComputerPDP11 extends Component {
/**
* saveMachineParms()
*
* @this {ComputerPDP11}
* @return {string|null}
*/
saveMachineParms()
@ -359,6 +378,7 @@ class ComputerPDP11 extends Component {
/**
* getUserID()
*
* @this {ComputerPDP11}
* @return {string}
*/
getUserID()
@ -1167,6 +1187,8 @@ class ComputerPDP11 extends Component {
/**
* resetUserID()
*
* @this {ComputerPDP11}
*/
resetUserID()
{
@ -1177,6 +1199,7 @@ class ComputerPDP11 extends Component {
/**
* queryUserID(fPrompt)
*
* @this {ComputerPDP11}
* @param {boolean} [fPrompt]
* @returns {string|null|undefined}
*/
@ -1265,6 +1288,7 @@ class ComputerPDP11 extends Component {
/**
* saveServerState(sUserID, sState)
*
* @this {ComputerPDP11}
* @param {string} sUserID
* @param {string|null} sState
*/

View file

@ -228,15 +228,6 @@ class CPUPDP11 extends Component {
if (DEBUGGER && this.dbg) {
this.dbg.init(this.flags.autoStart);
} else {
/*
* The Computer (this.cmp) knows if there's a Control Panel (this.panel), and the Control Panel
* knows if there's a "print" control (this.panel.controlPrint), and if there IS a "print" control
* but no debugger, the machine is probably misconfigured (most likely, the page simply neglected to
* load the Debugger component).
*
* However, we don't actually need to check all that; it's always safe use println(), regardless whether
* a Control Panel with a "print" control is present or not.
*/
this.status("No debugger detected");
}
if (!this.flags.autoStart) {

View file

@ -2751,10 +2751,7 @@ class DebuggerPDP11 extends Debugger {
*/
doClear(sCmd)
{
/*
* TODO: There should be a clear() component method that the Control Panel overrides to perform this function.
*/
if (this.controlPrint) this.controlPrint.value = "";
this.cmp.clearPanel();
}
/**

View file

@ -142,9 +142,6 @@ class Component {
this.clearError();
this.bitsMessage = bitsMessage || 0;
/** @type {Object|null} controlPrint is the HTML control, if any, that we can print to */
this.controlPrint = null;
this.cmp = null;
this.bus = null;
this.cpu = null;
@ -882,15 +879,17 @@ class Component {
*
* @this {Component}
* @param {string|null} sHTMLType is the type of the HTML control (eg, "button", "list", "text", "submit", "textarea", "canvas")
* @param {string} sBinding is the value of the 'binding' parameter stored in the HTML control's "data-value" attribute (eg, "reset")
* @param {string} sBinding is the value of the 'binding' parameter stored in the HTML control's "data-value" attribute (eg, 'print')
* @param {HTMLElement} control is the HTML control DOM object (eg, HTMLButtonElement)
* @param {string} [sValue] optional data value
* @return {boolean} true if binding was successful, false if unrecognized binding request
*/
setBinding(sHTMLType, sBinding, control, sValue)
{
var controlTextArea = /** @type {HTMLTextAreaElement} */ (control);
switch (sBinding) {
case "clear":
case 'clear':
if (!this.bindings[sBinding]) {
this.bindings[sBinding] = control;
control.onclick = (function(component) {
@ -902,36 +901,11 @@ class Component {
}(this));
}
return true;
case "print":
case 'print':
if (!this.bindings[sBinding]) {
this.bindings[sBinding] = control;
/*
* HACK: Save this particular HTML element so that the Debugger can access it, too
*/
this.controlPrint = control;
/*
* This was added for Firefox (Safari automatically clears the <textarea> on a page reload,
* but Firefox does not).
*/
control.value = "";
this.println = (function(control) {
return function printPanel(s, type) {
s = (type !== undefined? (type + ": ") : "") + (s || "");
/*
* Prevent the <textarea> from getting too large; otherwise, printing becomes slower and slower.
*/
if (COMPILED) {
if (control.value.length > 8192) {
control.value = control.value.substr(control.value.length - 4096);
}
}
control.value += s + "\n";
control.scrollTop = control.scrollHeight;
if (!COMPILED && window && window.console) console.log(s);
};
}(control));
this.bindings[sBinding] = controlTextArea;
/**
* Override this.notice() with a replacement function that eliminates the Component.alertUser() call
* Override this.notice() with a replacement function that eliminates the Component.alertUser() call.
*
* @this {Component}
* @param {string} s
@ -943,6 +917,40 @@ class Component {
this.println(s, this.idComponent);
return true;
};
/*
* This was added for Firefox (Safari will clear the <textarea> on a page reload, but Firefox does not).
*/
controlTextArea.value = "";
this.print = (function(controlTextArea) {
return function printPanel(s) {
/*
* Prevent the <textarea> from getting too large; otherwise, printing becomes slower and slower.
*/
if (COMPILED) {
if (controlTextArea.value.length > 8192) {
controlTextArea.value = controlTextArea.value.substr(controlTextArea.value.length - 4096);
}
}
controlTextArea.value += s;
controlTextArea.scrollTop = controlTextArea.scrollHeight;
};
}(controlTextArea));
this.println = (function(controlTextArea) {
return function printlnPanel(s, type) {
s = (type != null? (type + ": ") : "") + (s || "");
/*
* Prevent the <textarea> from getting too large; otherwise, printing becomes slower and slower.
*/
if (COMPILED) {
if (controlTextArea.value.length > 8192) {
controlTextArea.value = controlTextArea.value.substr(controlTextArea.value.length - 4096);
}
}
controlTextArea.value += s + "\n";
controlTextArea.scrollTop = controlTextArea.scrollHeight;
if (!COMPILED && window && window.console) console.log(s);
};
}(controlTextArea));
}
return true;
default:
@ -1021,7 +1029,7 @@ class Component {
}
/**
* println(s, type)
* println(s, type, id)
*
* For non-diagnostic messages, which components may override to control the destination/appearance of their output.
*