// $Id$
JSROOT.define([], () => {
"use strict";
if (typeof GO4 != "object") {
let e1 = new Error("condition.js requires GO4 to be already loaded");
e1.source = "condition.js";
throw e1;
}
// =========================================================================================
class ConditionEditor extends JSROOT.BasePainter {
constructor(dom, cond) {
super(dom);
this.cond = cond;
this.changes = ["dummy", "init"];
this.clearChanges();
}
isPolyCond() {
return ((this.cond._typename == "TGo4PolyCond") || (this.cond._typename == "TGo4ShapedCond"));
}
isEllipseCond() {
return (this.cond._typename == "TGo4ShapedCond");
}
/** @summary add identifier of changed element to list, make warning sign visible */
markChanged(key) {
// first avoid duplicate keys:
for (let index = 0; index < this.changes.length; index++) {
if (this.changes[index]== key) return;
}
this.changes.push(key);
console.log("Mark changed :%s", key);
this.selectDom().select(".buttonChangeLabel").style("display", null);// show warning sign
}
/** @summary clear changed elements' ist, make warning sign invisible */
clearChanges() {
for (let index = 0; index < this.changes.length ; index++) {
let removed = this.changes.pop();
console.log("Clear changes removed :%s", removed);
}
this.selectDom().select(".buttonChangeLabel").style("display", "none"); // hide warning sign
}
/** @summary scan changed value list and return optionstring to be send to server */
evaluateChanges(optionstring) {
let dom = this.selectDom(),
len = this.changes.length;
for (let index = 0; index < len ; index++) {
//let cursor=changes.pop();
let key = this.changes[index];
//console.log("Evaluate change key:%s", key);
// here mapping of key to editor field:
if(key=="limits")
{
let xmin = dom.select(".cond_xmin").property("value"),
xmax = dom.select(".cond_xmax").property("value");
optionstring += `&xmin=${xmin}&xmax=${xmax}`;
this.cond.fLow1 = xmin;
this.cond.fUp1 = xmax;
if (this.cond.fiDim == 2) {
let ymin = dom.select(".cond_ymin").property("value"),
ymax = dom.select(".cond_ymax").property("value");
this.cond.fLow2 = ymin;
this.cond.fUp2 = ymax;
optionstring += `&ymin=${ymin}&ymax=${ymax}`;
}
} else if (key == "polygon") {
let npoints = dom.select(".cut_points").property("value");
optionstring += "&npolygon="+npoints;
let values = dom.selectAll(".cut_values input").nodes();
// TODO: set display of polygon points
if (values.length != npoints*2)
return console.error('mismatch', values.length, npoints*2);
// always copy last point!
values[npoints*2-2].value = values[0].value;
values[npoints*2-1].value = values[1].value;
for(let i = 0; i < npoints; ++i) {
let x = values[i*2].value,
y = values[i*2+1].value;
optionstring += `&x${i}=${x}&y${i}=${y}`;
}
} else if (key == "ellinpts") {
let val = dom.select(".cond_ellipse_points").property("value");
optionstring += `&${key}=${val}`;
} else if (key == "ellicx") {
let val = dom.select(".cond_ellipse_cx").property("value");
optionstring += `&${key}=${val}`;
} else if (key == "ellicy") {
let val = dom.select(".cond_ellipse_cy").property("value");
optionstring += `&${key}=${val}`;
} else if (key == "ellia1") {
let val = dom.select(".cond_ellipse_a1").property("value");
optionstring += `&${key}=${val}`;
} else if (key == "ellia2") {
let val = dom.select(".cond_ellipse_a2").property("value");
optionstring += `&${key}=${val}`;
} else if (key == "ellishape") {
let val = dom.select(".cond_ellipse_iscircle").property("value");
optionstring += `&${key}=${val}`;
} else if (key == "ellith") {
let val = dom.select(".cond_ellipse_theta").property("value");
optionstring += `&${key}=${val}`;
} else if (key == "resultmode") {
let val = dom.select(".cond_execmode").property("value");
optionstring += `&${key}=${val}`;
} else if (key == "invertmode") {
let val = dom.select(".cond_invertmode").property("value");
optionstring += `&${key}=${val}`;
} else if (key == "visible") {
let arg = dom.select(".cond_visible").property("checked") ? 1 : 0;
optionstring += `&${key}=${arg}`;
} else if (key == "labeldraw") {
let arg = dom.select(".cond_label").property("checked") ? 1 : 0;
this.cond.fbLabelDraw = arg;
optionstring += `&${key}=${arg}`;
} else if (key == "limitsdraw"){
let arg = dom.select(".cond_limits").property("checked") ? 1 : 0;
this.cond.fbLimitsDraw = arg;
optionstring += `&${key}=${arg}`;
} else if (key == "intdraw") {
let arg = dom.select(".cond_integr").property("checked") ? 1 : 0;
this.cond.fbIntDraw = arg;
optionstring += `&${key}=${arg}`;
} else if (key == "xmeandraw") {
let arg = dom.select(".cond_xmean").property("checked") ? 1 : 0;
this.cond.fbXMeanDraw = arg;
optionstring += `&${key}=${arg}`;
} else if (key == "xrmsdraw") {
let arg = dom.select(".cond_xrms").property("checked") ? 1 : 0;
this.cond.fbXRMSDraw = arg;
optionstring += `&${key}=${arg}`;
} else if (key == "ymeandraw") {
let arg = dom.select(".cond_ymean").property("checked") ? 1 : 0;
this.cond.fbYMeanDraw = arg;
optionstring += `&${key}=${arg}`;
} else if (key == "yrmsdraw") {
let arg = dom.select(".cond_yrms").property("checked") ? 1 : 0;
this.cond.fbYRMSDraw = arg;
optionstring += `&${key}=${arg}`;
} else if (key == "xmaxdraw") {
let arg = dom.select(".cond_maxx").property("checked") ? 1 : 0;
this.cond.fbXMaxDraw = arg;
optionstring += `&${key}=${arg}`;
} else if (key=="ymaxdraw") {
let arg = dom.select(".cond_maxy").property("checked") ? 1 : 0;
this.cond.fbYMaxDraw = arg;
optionstring += `&${key}=${arg}`;
} else if (key=="cmaxdraw") {
let arg = dom.select(".cond_max").property("checked") ? 1 : 0;
this.cond.fbCMaxDraw = arg;
optionstring += `&${key}=${arg}`;
} else {
console.log(`Warning: evaluateChanges found unknown key: ${key}`);
}
}
console.log(`Resulting option string: ${optionstring}`);
return optionstring;
}
checkResize() {}
/** @summary change dimension of polygon
* @desc this only changes display of condition, not condition itself!
* note that condition is still changed in analysis only by evaluateChanges
* local condition copy is unchanged until we can display it somewhere. */
changePolygonDimension() {
if(!this.isPolyCond()) return;
let dom = this.selectDom(),
oldpoints = this.cond.fxCut.fNpoints,
npoints = dom.select(".cut_points").property("value");
//if(npoints==oldpoints) return; // no dimension change, do nothing - disabled, error if we again go back to original condition dimension
if (this.cond.fxCut) {
let body = dom.select(".cut_values tbody").html(""); // clear old contents
if (npoints > oldpoints) {
// insert last but one point into table:
// first points are unchanged:
for (let i = 0; i < oldpoints - 1; i++) {
let x = this.cond.fxCut.fX[i], y = this.cond.fxCut.fY[i];
body.append("tr").html(`
`);
}
// inserted points will reproduce values of last but one point:
let insx = this.cond.fxCut.fX[oldpoints - 2],
insy = this.cond.fxCut.fY[oldpoints - 2];
for (let i = oldpoints - 1; i < npoints - 1; i++)
body.append("tr").html(`
`);
// final point is kept as last point of old polygon, should
// match first point for closed tcutg:
let lastx = this.cond.fxCut.fX[oldpoints - 1],
lasty = this.cond.fxCut.fY[oldpoints - 1];
body.append("tr").html(`
`);
} else {
// remove last but one point from table:
for (let i = 0; i < npoints - 1; i++) {
let x = this.cond.fxCut.fX[i], y = this.cond.fxCut.fY[i];
body.append("tr").html(`
`);
}
// final point is kept as last point of old polygon, should
// match first point for closed tcutg:
let lastx = this.cond.fxCut.fX[oldpoints - 1],
lasty = this.cond.fxCut.fY[oldpoints - 1];
body.append("tr").html(`
`);
}
}
this.markChanged("polygon");
}
/** @summary enable/disable tab by index */
changeTab(action, indx) {
let dom = this.selectDom(),
btns = dom.select('.cond_tabs_header').selectAll("button").nodes(),
tabs = dom.selectAll('.tabs_body>div').nodes();
if (btns.length != tabs.length)
return console.error('mismatch in tabs sizes', btns.length, tabs.length);
d3.select(btns[indx]).attr('disabled', (action=="enable") ? null : "true");
// if that tab selected, find any other suitable
if ((action == "disable") && d3.select(btns[indx]).classed("active_btn")) {
let best = -1;
btns.forEach((btn,k) => {
if (!d3.select(btn).attr('disabled') && (k != indx) && (best < 0)) best = k;
});
if (best >= 0) {
d3.select(tabs[indx]).style("display", "none");
d3.select(tabs[best]).style("display", null);
d3.select(btns[indx]).classed("active_btn", false);
d3.select(btns[best]).classed("active_btn", true);
}
}
}
/** @summary refresh condition editor */
refreshEditor() {
let editor = this,
cond = this.cond,
dom = this.selectDom();
dom.select(".cond_name").text(cond.fName);
dom.select(".cond_type").text(cond._typename);
dom.select(".cond_execmode").node().value = cond.fbEnabled ? 0 : (cond.fbResult ? 1 : 2);
dom.select(".cond_invertmode").node().value = cond.fbTrue ? 0 : 1;
dom.select(".cond_xmin").property("value", cond.fLow1).on("change", () => this.markChanged("limits"));
dom.select(".cond_xmax").property("value", cond.fUp1).on("change", () => this.markChanged("limits"));
if (cond.fiDim==2) {
dom.select(".cond_ymin").property("value", cond.fLow2).on("change", () => this.markChanged("limits"));
dom.select(".cond_ymax").property("value", cond.fUp2).on("change", () => this.markChanged("limits"));
} else {
dom.select(".cond_ymin").attr('disabled', true);
dom.select(".cond_ymax").attr('disabled', true);
}
if(this.isPolyCond()) {
this.changeTab("enable", 1); // enable/disable by tab index
this.changeTab("disable", 0); // enable/disable by tab index
if (this.cond.fxCut) {
let numpoints = this.cond.fxCut.fNpoints;
dom.select(".cut_points").property("value", numpoints);
let body = dom.select(".cut_values tbody").html("").on("change", () => editor.markChanged("polygon"));
for(let i = 0; i < numpoints; i++) {
let x = this.cond.fxCut.fX[i];
let y = this.cond.fxCut.fY[i];
let row = body.append("tr").html(`