* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const { Scr } = require('../engine/XDefine');
const { XTools } = require('../engine/XTools');
const { XButton } = require('../engine/control/XButton');
const { XScroll } = require('../engine/control/XScroll');
const { XSelect } = require('../engine/control/XSelect');
const { X2DFast } = require('../engine/graphics/X2DFast');
const { XTexture } = require('../engine/graphics/XTexture');
const { CanvasInput } = require('./CanvasInput');
const { IrToPicture } = require('./IrToPicture');
const { LogParser } = require('./LogParser');
const { NapiLog } = require('./NapiLog');
const INTYPE_STR = ['state', 'depend', 'value', 'framestate', 'root', 'other'];
class IrViewer {
constructor(fn, result) {
this.t1_ = Date.now();
this.fileName_ = fn;
this.parser_ = new LogParser(result);
this.inited_ = false;
}
InitViewer(result) {
this.data_ = result;
this.direct_ = null;
this.selectPoint_ = [];
this.visable_ = null;
this.loaded_ = false;
this.offx_ = Scr.logicw / 2;
this.offy_ = 30;
let tx = 10;
let ty = 10;
let files = Object.keys(this.data_);
this.selectFile_ = new XSelect(files, files[0]);
this.selectFile_.move(tx, ty, 550, 20);
this.selectFile_.registCallback(this.changeFile.bind(this));
tx = 10;
ty += 30;
this.selectFunc_ = new XSelect([], '');
this.selectFunc_.move(tx, ty, 290, 20);
this.selectFunc_.registCallback(this.changeFunc.bind(this));
tx += 290 + 10;
this.selectMethod_ = new XSelect([], '');
this.selectMethod_.move(tx, ty, 250, 20);
this.selectMethod_.registCallback(this.changeMethod.bind(this));
tx = 10;
ty += 30;
this.btnGo_ = [];
this.mask_ = 0xffff;
for (let i = 0; i < INTYPE_STR.length; i++) {
let bname = INTYPE_STR[i] + '✔️';
let bw = X2DFast.gi().getTextWidth(bname, 14) + 6;
let btn = new XButton(tx, ty, bw, 20, bname);
btn.inTypeId_ = i;
btn.inTypeMask_ = 1;
btn.onClicked_ = () => {
btn.inTypeMask_ = 1 - btn.inTypeMask_;
btn.name_ = INTYPE_STR[btn.inTypeId_] + (btn.inTypeMask_ === 1 ? '✔️' : '❌');
this.mask_ = (this.mask_ & ~(1 << btn.inTypeId_)) | (btn.inTypeMask_ << btn.inTypeId_);
this.changeVisable();
};
this.btnGo_.push(btn);
tx += bw + 10;
}
tx = 10;
ty += 30;
let bms = [['隐藏选中(Hide selected)', () => { this.hideNode(0); }],
['隐藏未选中(Hide unselected)', () => { this.hideNode(1); }],
['显示隐藏(Show hide)', () => { this.hideNode(2); }],
['选中前继(Select pred)', () => { this.selectNode(0); }],
['选中后继(Select suc)', () => { this.selectNode(1); }],
['刷新(refresh)', () => { this.freshNode(); }]];
for (let bm of bms) {
let bw = X2DFast.gi().getTextWidth(bm[0], 14) + 6;
let btn = new XButton(tx, ty, bw, 20, bm[0]);
btn.onClicked_ = bm[1];
this.btnGo_.push(btn);
tx += bw + 10;
}
this.btnGo_.push(this.selectFile_, this.selectFunc_, this.selectMethod_);
this.btnGo_.sort((a, b) => {
return b.posY_ - a.posY_;
});
this.scrollY_ = new XScroll({ type: 'right' });
this.scrollX_ = new XScroll({ type: 'button' });
this.scrollY_.move(Scr.logicw - 20, 100, 20, Scr.logich - 100 - 20);
this.scrollX_.move(20, Scr.logich - 20, Scr.logicw - 40, 20);
this.hideNodeIds_ = [];
this.pointFile_ = files[0];
}
freshNode() {
this.scrollY_.setBarOff(0);
this.scrollX_.setBarOff(0.5);
IrToPicture.resetPicture(this.visable_.nodes, this.direct_.type.startsWith('block:'));
}
hideNode(type) {
if (type === 0) {
this.hideNodeIds_ = this.hideNodeIds_.concat(this.selectPoint_);
}
else if (type === 1) {
let nodes = this.visable_.nodes;
for (let k in nodes) {
if (this.selectPoint_.indexOf(parseInt(nodes[k].ir.id)) >= 0) {
continue;
}
this.hideNodeIds_.push(parseInt(nodes[k].ir.id));
}
}
else {
this.hideNodeIds_ = [];
}
this.changeVisable();
}
selectNode(type) {
let sel = new Set();
let nodes = this.visable_.nodes;
let lines = this.visable_.lines;
let hideChanged = false;
for (let l of lines) {
let n1 = nodes[l.fromId];
let n2 = nodes[l.toId];
let id1 = parseInt(n1.ir.id);
let id2 = parseInt(n2.ir.id);
let idx = -1;
if (type === 0 && (n1.mask & this.mask_) !== 0 && this.selectPoint_.indexOf(id2) >= 0) {
idx = this.hideNodeIds_.indexOf(id1);
sel.add(id1);
}
if (type === 1 && (n2.mask & this.mask_) !== 0 && this.selectPoint_.indexOf(id1) >= 0) {
idx = this.hideNodeIds_.indexOf(id2);
sel.add(id2);
}
if (idx >= 0) {
this.hideNodeIds_.splice(idx, 1);
hideChanged = true;
}
}
this.selectPoint_ = [...sel];
if (hideChanged) {
this.changeVisable();
}
}
loading() {
if (this.loaded_) {
return false;
}
if (this.parser_.parsing()) {
return true;
}
if (!this.inited_) {
this.inited_ = true;
this.InitViewer(this.parser_.output_);
return true;
}
let total = 1;
let procto = 1;
let loadonce = 1;
for (let file in this.data_) {
for (let func in this.data_[file]) {
for (let method of this.data_[file][func]) {
total++;
if (method.loaded) {
procto++;
continue;
}
if (loadonce <= 0) {
continue;
}
loadonce--;
method.irAll = IrToPicture.toPicture(method.irList, 1, method.type.startsWith('block:'));
method.loaded = true;
}
}
}
if (loadonce === 0) {
XTools.PROC_TO = 20 + procto / total * 80;
return true;
}
XTools.PROC_TO = 100;
this.loaded_ = true;
this.changeFile(this.pointFile_);
NapiLog.logInfo('load cost', Date.now() - this.t1_);
return true;
}
changeFile(name) {
this.pointFile_ = name;
let funcs = Object.keys(this.data_[this.pointFile_]);
this.selectFunc_.resetList(funcs, funcs[0]);
this.changeFunc(funcs[0]);
}
changeFunc(name) {
this.pointFunc_ = name;
let methods = [];
for (let i = 0; i < this.data_[this.pointFile_][this.pointFunc_].length; i++) {
methods.push((i + 1) + ',' + this.data_[this.pointFile_][this.pointFunc_][i].type);
}
this.selectMethod_.resetList(methods, methods[0]);
this.changeMethod(methods[0]);
}
changeMethod(name) {
this.pointMethod_ = name;
let p = parseInt(name.split(',')[0]) - 1;
this.direct_ = this.data_[this.pointFile_][this.pointFunc_][p];
this.changeVisable();
}
changeVisable() {
this.visable_ = this.direct_.irAll;
let nodes = this.visable_.nodes;
let lines = this.visable_.lines;
let showNodes = [];
for (let k in nodes) {
let n = nodes[k];
if (this.hideNodeIds_.indexOf(parseInt(n.ir.id)) >= 0) {
n.hide = true;
}
else {
n.hide = (n.mask & this.mask_) === 0;
if (!n.hide) {
showNodes.push(k);
}
}
}
for (let k of showNodes) {
let n = nodes[k];
for (let i = 0; i < 5; i++) {
if ((this.mask_ & (1 << i) !== 0) && (n.mask & (1 << i) !== 0)) {
for (let id of n.ir.in[i]) {
nodes[id].hide = false;
}
}
}
}
for (let k in nodes) {
let n = nodes[k];
if (this.hideNodeIds_.indexOf(parseInt(n.ir.id)) >= 0) {
n.hide = true;
}
}
this.scrollY_.setBarOff(0);
this.scrollX_.setBarOff(0.5);
}
makeLevely(nodes) {
let levely = new Set();
for (let k in nodes) {
let n = nodes[k];
if (n.hide) {
continue;
}
if (n.deep !== IrToPicture.INVALID_DEEP) {
levely.add(n.pos.y);
}
}
return Array.from(levely).sort((a, b) => { return parseInt(a) - parseInt(b) });
}
drawSmallMap(nodes, x1, x2, y1, y2) {
if (x1 === x2 || y2 === y1) {
return;
}
let [tx, ty, w, h] = this.smallMapRect;
X2DFast.gi().fillRect(tx, ty, w, h, 0x80000000);
let sw = w / (x2 - x1);
let sh = h / (y2 - y1);
let dh = Math.max(20 * sh, 1);
for (let k in nodes) {
let n = nodes[k];
if (n.hide) {
continue;
}
let dx = n.pos.x - x1;
let dy = n.pos.y - y1;
let dw = Math.max((n.nameWidth + 6) * sw, 1);
if (this.selectPoint_.indexOf(parseInt(k)) >= 0) {
if (this.drapSelect_) {
dx += this.drapSelect_.dx;
dy += this.drapSelect_.dy;
}
X2DFast.gi().fillRect(tx + (dx - 3) * sw, ty + (dy - 10) * sh, dw, dh, 0xff000000);
}
else {
let selectWith = false;
for (let inl of n.in) {
if (this.selectPoint_.indexOf(parseInt(inl.fromId)) >= 0) {
selectWith = true;
break;
}
}
if (!selectWith) {
for (let outl of n.out) {
if (this.selectPoint_.indexOf(parseInt(outl.toId)) >= 0) {
selectWith = true;
break;
}
}
}
if (selectWith) {
X2DFast.gi().fillRect(tx + (dx - 3) * sw, ty + (dy - 10) * sh, dw, dh, 0xff000000);
}
else {
X2DFast.gi().fillRect(tx + (dx - 3) * sw, ty + (dy - 10) * sh, dw, dh, XTools.CONFIG.NodeColor[n.type]);
}
}
}
X2DFast.gi().drawRect(tx - (this.offx_ + x1) * sw, ty - (this.offy_ + y1) * sh, Math.min(Scr.logicw * sw, w), Math.min(Scr.logich * sh, h), 0xff00ff00, 1);
}
onDraw() {
if (this.loading()) {
X2DFast.gi().drawText('Loading ' + XTools.PROC_TO.toFixed(1) + '%', 20, Scr.logicw / 2, Scr.logich / 2, 1, 1, 0, -2, -2, 0xff000000);
return;
}
let smallMapSize = parseInt(Math.min(Scr.logicw / 3, Scr.logich / 3));
this.smallMapRect = [Scr.logicw - 50 - smallMapSize, 50, smallMapSize, smallMapSize];
let nodes = this.visable_.nodes;
let lines = this.visable_.lines;
let levely = this.makeLevely(nodes);
let maxx = -9999;
let minx = 9999;
let mouseOn = -1;
let collect = {
singleCount: 0,
showCount: 0,
nodeCount: Object.keys(nodes).length,
};
for (let k in nodes) {
let n = nodes[k];
if (n.hide) {
continue;
}
collect.showCount++;
if (n.deep !== IrToPicture.INVALID_DEEP) {
collect.singleCount++;
if (maxx < n.pos.x + n.nameWidth + this.offx_) {
maxx = n.pos.x + n.nameWidth + this.offx_;
}
if (minx > n.pos.x + this.offx_) {
minx = n.pos.x + this.offx_;
}
}
if (XTools.InRect(XTools.MOUSE_POS.x, XTools.MOUSE_POS.y, n.pos.x + this.offx_ - 3, n.pos.y + this.offy_ - 10, n.nameWidth + 6, 20)) {
mouseOn = k;
}
n.outhx = {};
}
this.selectLines_ = [];
let mmx1 = this.drawLines(this.offx_, this.offy_, nodes, lines, levely, [minx - 20, maxx + 20], false);
for (let k in nodes) {
let n = nodes[k];
if (n.deep === IrToPicture.INVALID_DEEP) {
if (n.pos.x === IrToPicture.INVALID_DEEP) {
n.pos.x = mmx1[1] - this.offx_ + 20;
}
}
if (n.hide) {
continue;
}
let dx = n.pos.x + this.offx_;
let dy = n.pos.y + this.offy_;
if (this.selectPoint_.indexOf(parseInt(k)) >= 0) {
if (this.drapSelect_) {
dx += this.drapSelect_.dx;
dy += this.drapSelect_.dy;
}
X2DFast.gi().fillRect(dx - 3, dy - 10, n.nameWidth + 6, 20, 0xffffff00);
X2DFast.gi().drawRect(dx - 3, dy - 10, n.nameWidth + 6, 20, 0xff000000, 2);
}
else {
X2DFast.gi().fillRect(dx - 3, dy - 10, n.nameWidth + 6, 20, XTools.CONFIG.NodeColor[n.type]);
let selectWith = false;
for (let inl of n.in) {
if (this.selectPoint_.indexOf(parseInt(inl.fromId)) >= 0) {
selectWith = true;
break;
}
}
if (!selectWith) {
for (let outl of n.out) {
if (this.selectPoint_.indexOf(parseInt(outl.toId)) >= 0) {
selectWith = true;
break;
}
}
}
if (selectWith) {
X2DFast.gi().drawRect(dx - 3, dy - 10, n.nameWidth + 6, 20, 0xff000000, 2);
}
}
X2DFast.gi().drawText(n.name, 14, dx + n.nameWidth / 2, dy + 2, 1, 1, 0, -2, -2, 0xff000000);
}
this.drawLines(this.offx_, this.offy_, nodes, lines, levely, [minx - 20, maxx + 20], true);
for (let ln of this.selectLines_) {
let [r, g, b, a] = XTexture.ExpandColor(ln[4]);
r = Math.max(0, r * 255 - 32);
g = Math.max(0, g * 255 - 32);
b = Math.max(0, b * 255 - 32);
this.drawLine(ln[0], ln[1], ln[2], ln[3], 0xff000000 | (r << 16) | (g << 8) | b, ln[5] + 1);
}
if (mouseOn >= 0) {
let n = nodes[mouseOn];
let w = n.ir.maxDetailWidth + 2;
let h = n.ir.detailList.length * 16 + 2;
let x = XTools.MOUSE_POS.x - w;
let y = XTools.MOUSE_POS.y - h;
if (x < 10) {
x = 10;
}
if (y < 130) {
y = 130;
}
X2DFast.gi().fillRect(x, y, w, h, (XTools.CONFIG.NodeColor[n.type] & 0xffffff) | 0xC0000000);
for (let i = 0; i < n.ir.detailList.length; i++) {
X2DFast.gi().drawText(n.ir.detailList[i], 14, x + 1, y + 1 + i * 16, 1, 1, 0, -1, -1, 0xff000000);
}
}
for (let btn of this.btnGo_) {
btn.draw();
}
let x1 = 9999;
let y1 = 9999;
let x2 = -9999;
let y2 = -9999;
for (let k in nodes) {
let n = nodes[k];
if (n.hide) {
continue;
}
if (n.pos.x < x1) {
x1 = n.pos.x;
}
if (n.pos.x + n.nameWidth > x2) {
x2 = n.pos.x + n.nameWidth;
}
if (n.pos.y < y1) {
y1 = n.pos.y;
}
if (n.pos.y + n.nameWidth > y2) {
y2 = n.pos.y + IrToPicture.NODEH;
}
}
x1 = Math.min(mmx1[0] - this.offx_, x1) - Scr.logicw / 3;
x2 = Math.max(mmx1[1] - this.offx_, x2) + Scr.logicw / 3;
y1 = y1 - Scr.logich / 3;
y2 = y2 + Scr.logich / 3;
this.dragScoll = {
x1: x1,
x2: x2,
y1: y1,
y2: y2,
};
let scrollW = x2 - x1;
let scrollH = y2 - y1;
this.dragScoll.hh = scrollH - Scr.logich;
this.dragScoll.ww = scrollW - Scr.logicw;
if (this.dragScoll.hh < 1) {
this.dragScoll.hh = 1;
}
if (this.dragScoll.ww < 1) {
this.dragScoll.ww = 1;
}
if (this.drapBackground_) {
this.scrollY_.setBarOff(-(this.offy_ + this.dragScoll.y1) / this.dragScoll.hh);
this.scrollX_.setBarOff(-(this.offx_ + this.dragScoll.x1) / this.dragScoll.ww);
}
else {
this.offy_ = (-this.scrollY_.getBarOff()) * this.dragScoll.hh - this.dragScoll.y1;
this.offx_ = (-this.scrollX_.getBarOff()) * this.dragScoll.ww - this.dragScoll.x1;
}
if (this.dragScoll.hh > 1) {
this.scrollY_.move(Scr.logicw - 20, 100, 20, Scr.logich - 100 - 20).draw();
}
if (this.dragScoll.ww > 1) {
this.scrollX_.move(20, Scr.logich - 20, Scr.logicw - 40, 20).draw();
}
this.drawSmallMap(nodes, x1, x2, y1, y2);
if (this.searchInput) {
let x = this.searchInput.pos[0];
let y = this.searchInput.pos[1];
let w = this.searchInput.pos[2];
let h = this.searchInput.pos[3];
X2DFast.gi().fillRect(x, y, w, h, 0x80000000);
let searchResultTxt =
this.searchInput.result.length === 0 ? '0/0' :
this.searchInput.point + 1 + '/' + this.searchInput.result.length;
this.searchInput.btnUp.move(x + 20, y + 50, 32, 24).draw();
X2DFast.gi().drawText(
searchResultTxt,
20,
x + w / 2,
y + 50 + 12,
1,
1,
0,
-2,
-2,
0xffffffff
) + 16;
this.searchInput.btnDown.move(x + w - 20 - 32, y + 50, 32, 24).draw();
this.searchInput.btnClose.move(x + w - 40, y + 10, 30, 30).draw();
}
}
checkLevel(levely, n1, n2) {
let i1 = levely.indexOf(n1.pos.y);
let i2 = levely.indexOf(n2.pos.y);
return i1 + 1 === i2;
}
drawLines(offx, offy, nodes, lines, levely, mmx, select) {
let aaa = 5;
if (true) {
aaa = -5;
for (let l of lines) {
let n1 = nodes[l.fromId];
let n2 = nodes[l.toId];
if (n1.hide || n2.hide) {
continue;
}
let lor = n1.pos.x + n2.pos.x < -50 ? 0 : 1;
if (this.checkLevel(levely, n1, n2)) { }
else {
if (!(n1.outh[l.outNum] in n1.outhx)) {
mmx[lor] += lor === 0 ? aaa : -aaa;
n1.outhx[n1.outh[l.outNum]] = mmx[lor];
}
}
}
}
let mmx1 = [mmx[0], mmx[1]];
for (let l of lines) {
let n1 = nodes[l.fromId];
let n2 = nodes[l.toId];
if (n1.hide || n2.hide) {
continue;
}
let x1 = n1.pos.x + n1.nameWidth - 5 + offx - n1.ltypes.indexOf(l.lineType) * 5;
let y1 = n1.pos.y + 10 + offy;
let x2 = n2.pos.x + n2.nameWidth - 5 + offx - l.inNum * 5;
let y2 = n2.pos.y - 10 + offy;
let lor = n1.pos.x + n2.pos.x < -50 ? 0 : 1;
let selected = false;
if (this.selectPoint_.indexOf(l.fromId) >= 0 || this.selectPoint_.indexOf(l.toId) >= 0) {
selected = true;
if (this.drapSelect_) {
if (this.selectPoint_.indexOf(l.fromId) >= 0) {
x1 += this.drapSelect_.dx;
y1 += this.drapSelect_.dy;
}
if (this.selectPoint_.indexOf(l.toId) >= 0) {
x2 += this.drapSelect_.dx;
y2 += this.drapSelect_.dy;
}
}
}
if (select !== selected) {
if (this.checkLevel(levely, n1, n2)) { }
else {
mmx[lor] += lor === 0 ? -aaa : aaa;
}
continue;
}
let c = 0xffc0c0c0;
let lw = 1;
if (selected) {
c = XTools.CONFIG.LineColor[l.lineType];
lw = 2;
}
let ls = [];
if (this.checkLevel(levely, n1, n2)) {
ls.push([x1, y1, x1, y1 + n1.outh[l.outNum], c, lw]);
ls.push([x1, y1 + n1.outh[l.outNum], x2, y1 + n1.outh[l.outNum], c, lw]);
ls.push([x2, y1 + n1.outh[l.outNum], x2, y2, c, lw]);
}
else {
let lx = n1.outhx[n1.outh[l.outNum]];
let ly = n2.inh[l.fromId + l.lineType];
ls.push([x1, y1, x1, y1 + n1.outh[l.outNum], c, lw]);
ls.push([x1, y1 + n1.outh[l.outNum], lx, y1 + n1.outh[l.outNum], c, lw]);
ls.push([lx, y1 + n1.outh[l.outNum], lx, y2 - ly, c, lw]);
ls.push([lx, y2 - ly, x2, y2 - ly, c, lw]);
ls.push([x2, y2 - ly, x2, y2, c, lw]);
mmx[lor] += lor === 0 ? -aaa : aaa;
}
let mouseOn = false;
for (let ln of ls) {
mouseOn |= this.drawLine(...ln);
}
if (mouseOn) {
this.selectLines_.push(...ls);
}
}
return [Math.min(mmx1[0], mmx[0]), Math.max(mmx1[1], mmx[1])];
}
drawLine(x1, y1, x2, y2, c, lw = 1) {
if (x1 === x2) {
if (y1 > y2) {
[y1, y2] = [y2, y1];
}
X2DFast.px2f.fillRect(x1, y1, lw, y2 - y1 + lw, c);
if (XTools.InRect(XTools.MOUSE_POS.x, XTools.MOUSE_POS.y, x1 - 1, y1, lw + 2, y2 - y1)) {
return true;
}
}
else if (y1 === y2) {
if (x1 > x2) {
[x1, x2] = [x2, x1];
}
X2DFast.px2f.fillRect(x1, y1, x2 - x1, lw, c);
if (XTools.InRect(XTools.MOUSE_POS.x, XTools.MOUSE_POS.y, x1, y1 - 1, x2 - x1, lw + 2)) {
return true;
}
}
else {
}
return false;
}
locateNode(p) {
this.selectPoint_ = [parseInt(p)];
let nodes = this.visable_.nodes;
let n = nodes[p];
this.offx_ = Scr.logicw / 2 - n.pos.x;
this.offy_ = Scr.logich / 2 - n.pos.y;
this.scrollY_.setBarOff(-(this.offy_ + this.dragScoll.y1) / this.dragScoll.hh);
this.scrollX_.setBarOff(-(this.offx_ + this.dragScoll.x1) / this.dragScoll.ww);
this.offy_ = (-this.scrollY_.getBarOff()) * this.dragScoll.hh - this.dragScoll.y1;
this.offx_ = (-this.scrollX_.getBarOff()) * this.dragScoll.ww - this.dragScoll.x1;
}
findNext() {
if (this.searchInput) {
this.searchInput.point += 1;
if (this.searchInput.point >= this.searchInput.result.length) {
this.searchInput.point = 0;
}
this.locateNode(this.searchInput.result[this.searchInput.point]);
}
}
resetOffset(x, y) {
let [tx, ty, w, h] = this.smallMapRect;
let [x1, y1, x2, y2] = [this.dragScoll.x1, this.dragScoll.y1, this.dragScoll.x2, this.dragScoll.y2];
if (x1 === x2 || y1 === y2) {
return;
}
let sw = w / (x2 - x1);
let sh = h / (y2 - y1);
this.offx_ = (tx - x + Scr.logicw * sw / 2) / sw - x1;
this.offy_ = (ty - y + Scr.logich * sh / 2) / sh - y1;
this.scrollY_.setBarOff(-(this.offy_ + this.dragScoll.y1) / this.dragScoll.hh);
this.scrollX_.setBarOff(-(this.offx_ + this.dragScoll.x1) / this.dragScoll.ww);
this.offy_ = (-this.scrollY_.getBarOff()) * this.dragScoll.hh - this.dragScoll.y1;
this.offx_ = (-this.scrollX_.getBarOff()) * this.dragScoll.ww - this.dragScoll.x1;
}
checkMsgAndDrapSelect_(msg, x, y) {
if (msg === 3 && this.drapSelect_) {
let nodes = this.visable_.nodes;
for (let k of this.selectPoint_) {
nodes[k].pos.x += this.drapSelect_.dx;
nodes[k].pos.y += this.drapSelect_.dy;
}
this.drapSelect_ = null;
}
}
checkDrapBackground_(msg, x, y) {
if (this.drapBackground_) {
if (msg === 2) {
this.offx_ -= this.drapBackground_.x - x;
this.offy_ -= this.drapBackground_.y - y;
this.drapBackground_.x = x;
this.drapBackground_.y = y;
}
return true;
}
return false;
}
checkDrapSelect_(msg, x, y) {
if (this.drapSelect_) {
if (msg === 2) {
if (Math.abs(this.drapSelect_.x - x) > 10 ||
Math.abs(this.drapSelect_.y - y) > 10 ||
this.drapSelect_.dx !== 0 ||
this.drapSelect_.dy !== 0) {
this.drapSelect_.dx -= this.drapSelect_.x - x;
this.drapSelect_.dy -= this.drapSelect_.y - y;
this.drapSelect_.x = x;
this.drapSelect_.y = y;
}
}
return true;
}
return false;
}
checkSearchInput(msg, x, y) {
if (this.searchInput) {
if (XTools.InRect(x, y, ...this.searchInput.pos)) {
if (this.searchInput.btnUp.onTouch(msg, x, y)) {
if (this.searchInput.btnUp.isClicked()) {
this.searchInput.point -= 1;
if (this.searchInput.point < 0) {
this.searchInput.point = this.searchInput.result.length - 1;
}
this.locateNode(this.searchInput.result[this.searchInput.point]);
}
}
if (this.searchInput.btnDown.onTouch(msg, x, y)) {
if (this.searchInput.btnDown.isClicked()) {
this.findNext();
}
}
if (this.searchInput.btnClose.onTouch(msg, x, y)) {
if (this.searchInput.btnClose.isClicked()) {
this.searchInput = null;
CanvasInput.HideEx();
}
}
return true;
}
return false;
}
return false;
}
checkMsg(msg, x, y) {
if (msg === 1) {
let nodes = this.visable_.nodes;
for (let k in nodes) {
let n = nodes[k];
if (n.hide) {
continue;
}
if (XTools.InRect(x, y, n.pos.x + this.offx_ - 3, n.pos.y + this.offy_ - 10, n.nameWidth + 6, 20)) {
if (XTools.KEY_CTRL) {
this.selectPoint_.push(parseInt(k));
}
else {
if (this.selectPoint_.indexOf(parseInt(k)) < 0) {
this.selectPoint_ = [parseInt(k)];
}
}
this.drapSelect_ = {
x: x,
y: y,
dx: 0,
dy: 0,
};
return true;
}
}
this.selectPoint_ = [];
}
return false;
}
onTouch(msg, x, y) {
if (this.loading()) {
return true;
}
if (this.smallMapLocked_) {
if (msg === 2) {
this.resetOffset(x, y);
}
if (msg === 3) {
this.smallMapLocked_ = false;
}
return true;
}
if (msg === 6) {
this.drapBackground_ = null;
}
this.checkMsgAndDrapSelect_(msg, x, y)
this.checkDrapBackground_(msg, x, y)
this.checkDrapSelect_(msg, x, y)
if (this.scrollX_.onTouch(msg, x, y)) {
return true;
}
if (this.scrollY_.onTouch(msg, x, y)) {
return true;
}
if (XTools.InRect(x, y, ...this.smallMapRect)) {
if (msg === 1) {
this.resetOffset(x, y);
this.smallMapLocked_ = true;
}
return true;
}
this.checkSearchInput(msg, x, y)
for (let i = this.btnGo_.length - 1; i >= 0; i--) {
if (this.btnGo_[i].onTouch(msg, x, y)) {
return true;
}
}
this.checkMsg(msg, x, y)
if (msg === 4) {
this.drapBackground_ = {
x: x,
y: y,
};
}
return false;
}
onKey(k) {
if (this.loading()) {
return true;
}
if (this.searchInput) {
return true;
}
switch (k) {
case 'PageUp':
this.selectNode(0);
return true;
case 'PageDown':
this.selectNode(1);
return true;
case 'H':
case 'h':
this.hideNode(0);
return true;
case ' ':
this.hideNode(1);
return true;
case 'S':
case 's':
this.hideNode(2);
return true;
case 'Enter':
this.freshNode();
return true;
}
if (k === 'ctrl+f' || k === 'ctrl+F') {
this.searchInput = {
pos: [(Scr.logicw - 300), Scr.logich / 2, 200, 80],
result: [],
point: 0,
btnUp: new XButton(0, 0, 0, 0, '<'),
btnDown: new XButton(0, 0, 0, 0, '>'),
btnClose: new XButton(0, 0, 0, 0, '❌'),
};
let x = this.searchInput.pos[0];
let y = this.searchInput.pos[1];
let w = this.searchInput.pos[2];
let h = this.searchInput.pos[3];
this.searchInput.Open = () => {
CanvasInput.Reset(x, y + 10, w - 32 - 40, 32, '', null, (v) => {
function isRegExp(s) {
try {
new RegExp(s);
return true;
} catch (e) {
return false;
}
}
this.searchInput.result = [];
if (v.length > 0) {
let nodes = this.visable_.nodes;
this.selectPoint_ = [];
for (let i in nodes) {
let n = nodes[i];
let searchName;
if (XTools.CONFIG.OpTypeJsBytecode.indexOf(n.ir.op) >= 0) {
searchName = n.ir.bytecode;
}
else if (n.ir.typedop) {
searchName = n.ir.typedop;
}
else {
searchName = n.ir.op;
}
if (n.ir.id === v || searchName.indexOf(v) >= 0 || (isRegExp(v) && searchName.match(v))) {
this.searchInput.result.push(i);
}
}
if (this.searchInput.result.length > 0) {
this.locateNode(this.searchInput.result[0]);
this.searchInput.point = 0;
}
}
}, this.findNext.bind(this));
};
CanvasInput.SetSafeArea(...this.searchInput.pos);
this.searchInput.Open();
}
return false;
}
}
module.exports = {
IrViewer
};