14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ciconst { Scr } = require('../engine/XDefine');
174514f5e3Sopenharmony_ciconst { XTools } = require('../engine/XTools');
184514f5e3Sopenharmony_ciconst { XButton } = require('../engine/control/XButton');
194514f5e3Sopenharmony_ciconst { XScroll } = require('../engine/control/XScroll');
204514f5e3Sopenharmony_ciconst { XSelect } = require('../engine/control/XSelect');
214514f5e3Sopenharmony_ciconst { X2DFast } = require('../engine/graphics/X2DFast');
224514f5e3Sopenharmony_ciconst { XTexture } = require('../engine/graphics/XTexture');
234514f5e3Sopenharmony_ciconst { CanvasInput } = require('./CanvasInput');
244514f5e3Sopenharmony_ciconst { IrToPicture } = require('./IrToPicture');
254514f5e3Sopenharmony_ciconst { LogParser } = require('./LogParser');
264514f5e3Sopenharmony_ciconst { NapiLog } = require('./NapiLog');
274514f5e3Sopenharmony_ci
284514f5e3Sopenharmony_ciconst INTYPE_STR = ['state', 'depend', 'value', 'framestate', 'root', 'other'];
294514f5e3Sopenharmony_ci
304514f5e3Sopenharmony_ciclass IrViewer {
314514f5e3Sopenharmony_ci  constructor(fn, result) {
324514f5e3Sopenharmony_ci    this.t1_ = Date.now();
334514f5e3Sopenharmony_ci    this.fileName_ = fn;
344514f5e3Sopenharmony_ci    this.parser_ = new LogParser(result);
354514f5e3Sopenharmony_ci    this.inited_ = false;
364514f5e3Sopenharmony_ci  }
374514f5e3Sopenharmony_ci  InitViewer(result) {
384514f5e3Sopenharmony_ci    this.data_ = result;
394514f5e3Sopenharmony_ci    this.direct_ = null;
404514f5e3Sopenharmony_ci    this.selectPoint_ = [];
414514f5e3Sopenharmony_ci    this.visable_ = null;
424514f5e3Sopenharmony_ci
434514f5e3Sopenharmony_ci    this.loaded_ = false;
444514f5e3Sopenharmony_ci
454514f5e3Sopenharmony_ci    this.offx_ = Scr.logicw / 2;
464514f5e3Sopenharmony_ci    this.offy_ = 30;
474514f5e3Sopenharmony_ci
484514f5e3Sopenharmony_ci    let tx = 10;
494514f5e3Sopenharmony_ci    let ty = 10;
504514f5e3Sopenharmony_ci    let files = Object.keys(this.data_);
514514f5e3Sopenharmony_ci    this.selectFile_ = new XSelect(files, files[0]);
524514f5e3Sopenharmony_ci    this.selectFile_.move(tx, ty, 550, 20);
534514f5e3Sopenharmony_ci    this.selectFile_.registCallback(this.changeFile.bind(this));
544514f5e3Sopenharmony_ci
554514f5e3Sopenharmony_ci    tx = 10;
564514f5e3Sopenharmony_ci    ty += 30;
574514f5e3Sopenharmony_ci    this.selectFunc_ = new XSelect([], '');
584514f5e3Sopenharmony_ci    this.selectFunc_.move(tx, ty, 290, 20);
594514f5e3Sopenharmony_ci    this.selectFunc_.registCallback(this.changeFunc.bind(this));
604514f5e3Sopenharmony_ci
614514f5e3Sopenharmony_ci    tx += 290 + 10;
624514f5e3Sopenharmony_ci    this.selectMethod_ = new XSelect([], '');
634514f5e3Sopenharmony_ci    this.selectMethod_.move(tx, ty, 250, 20);
644514f5e3Sopenharmony_ci    this.selectMethod_.registCallback(this.changeMethod.bind(this));
654514f5e3Sopenharmony_ci
664514f5e3Sopenharmony_ci    tx = 10;
674514f5e3Sopenharmony_ci    ty += 30;
684514f5e3Sopenharmony_ci    this.btnGo_ = [];
694514f5e3Sopenharmony_ci    this.mask_ = 0xffff;
704514f5e3Sopenharmony_ci    for (let i = 0; i < INTYPE_STR.length; i++) {
714514f5e3Sopenharmony_ci      let bname = INTYPE_STR[i] + '✔️'; //❌
724514f5e3Sopenharmony_ci      let bw = X2DFast.gi().getTextWidth(bname, 14) + 6;
734514f5e3Sopenharmony_ci      let btn = new XButton(tx, ty, bw, 20, bname);
744514f5e3Sopenharmony_ci      btn.inTypeId_ = i;
754514f5e3Sopenharmony_ci      btn.inTypeMask_ = 1;
764514f5e3Sopenharmony_ci      btn.onClicked_ = () => {
774514f5e3Sopenharmony_ci        btn.inTypeMask_ = 1 - btn.inTypeMask_;
784514f5e3Sopenharmony_ci        btn.name_ = INTYPE_STR[btn.inTypeId_] + (btn.inTypeMask_ === 1 ? '✔️' : '❌');
794514f5e3Sopenharmony_ci        this.mask_ = (this.mask_ & ~(1 << btn.inTypeId_)) | (btn.inTypeMask_ << btn.inTypeId_);
804514f5e3Sopenharmony_ci        this.changeVisable();
814514f5e3Sopenharmony_ci      };
824514f5e3Sopenharmony_ci      this.btnGo_.push(btn);
834514f5e3Sopenharmony_ci      tx += bw + 10;
844514f5e3Sopenharmony_ci    }
854514f5e3Sopenharmony_ci
864514f5e3Sopenharmony_ci    tx = 10;
874514f5e3Sopenharmony_ci    ty += 30;
884514f5e3Sopenharmony_ci    let bms = [['隐藏选中(Hide selected)', () => { this.hideNode(0); }],
894514f5e3Sopenharmony_ci    ['隐藏未选中(Hide unselected)', () => { this.hideNode(1); }],
904514f5e3Sopenharmony_ci    ['显示隐藏(Show hide)', () => { this.hideNode(2); }],
914514f5e3Sopenharmony_ci    ['选中前继(Select pred)', () => { this.selectNode(0); }],
924514f5e3Sopenharmony_ci    ['选中后继(Select suc)', () => { this.selectNode(1); }],
934514f5e3Sopenharmony_ci    ['刷新(refresh)', () => { this.freshNode(); }]];
944514f5e3Sopenharmony_ci    for (let bm of bms) {
954514f5e3Sopenharmony_ci      let bw = X2DFast.gi().getTextWidth(bm[0], 14) + 6;
964514f5e3Sopenharmony_ci      let btn = new XButton(tx, ty, bw, 20, bm[0]);
974514f5e3Sopenharmony_ci      btn.onClicked_ = bm[1];
984514f5e3Sopenharmony_ci      this.btnGo_.push(btn);
994514f5e3Sopenharmony_ci      tx += bw + 10;
1004514f5e3Sopenharmony_ci    }
1014514f5e3Sopenharmony_ci
1024514f5e3Sopenharmony_ci    this.btnGo_.push(this.selectFile_, this.selectFunc_, this.selectMethod_);
1034514f5e3Sopenharmony_ci    this.btnGo_.sort((a, b) => {
1044514f5e3Sopenharmony_ci      return b.posY_ - a.posY_;
1054514f5e3Sopenharmony_ci    });
1064514f5e3Sopenharmony_ci
1074514f5e3Sopenharmony_ci    this.scrollY_ = new XScroll({ type: 'right' });
1084514f5e3Sopenharmony_ci    this.scrollX_ = new XScroll({ type: 'button' });
1094514f5e3Sopenharmony_ci    this.scrollY_.move(Scr.logicw - 20, 100, 20, Scr.logich - 100 - 20);
1104514f5e3Sopenharmony_ci    this.scrollX_.move(20, Scr.logich - 20, Scr.logicw - 40, 20);
1114514f5e3Sopenharmony_ci
1124514f5e3Sopenharmony_ci    this.hideNodeIds_ = [];
1134514f5e3Sopenharmony_ci    this.pointFile_ = files[0];
1144514f5e3Sopenharmony_ci  }
1154514f5e3Sopenharmony_ci  freshNode() {
1164514f5e3Sopenharmony_ci    this.scrollY_.setBarOff(0);
1174514f5e3Sopenharmony_ci    this.scrollX_.setBarOff(0.5);
1184514f5e3Sopenharmony_ci    IrToPicture.resetPicture(this.visable_.nodes, this.direct_.type.startsWith('block:'));
1194514f5e3Sopenharmony_ci  }
1204514f5e3Sopenharmony_ci  hideNode(type) {
1214514f5e3Sopenharmony_ci    if (type === 0) { //隐藏选中
1224514f5e3Sopenharmony_ci      this.hideNodeIds_ = this.hideNodeIds_.concat(this.selectPoint_);
1234514f5e3Sopenharmony_ci    }
1244514f5e3Sopenharmony_ci    else if (type === 1) { //隐藏未选中
1254514f5e3Sopenharmony_ci      let nodes = this.visable_.nodes;
1264514f5e3Sopenharmony_ci      for (let k in nodes) {
1274514f5e3Sopenharmony_ci        if (this.selectPoint_.indexOf(parseInt(nodes[k].ir.id)) >= 0) {
1284514f5e3Sopenharmony_ci          continue;
1294514f5e3Sopenharmony_ci        }
1304514f5e3Sopenharmony_ci        this.hideNodeIds_.push(parseInt(nodes[k].ir.id));
1314514f5e3Sopenharmony_ci      }
1324514f5e3Sopenharmony_ci    }
1334514f5e3Sopenharmony_ci    else { //显示所有
1344514f5e3Sopenharmony_ci      this.hideNodeIds_ = [];
1354514f5e3Sopenharmony_ci    }
1364514f5e3Sopenharmony_ci    this.changeVisable();
1374514f5e3Sopenharmony_ci  }
1384514f5e3Sopenharmony_ci  selectNode(type) {
1394514f5e3Sopenharmony_ci    let sel = new Set();
1404514f5e3Sopenharmony_ci    let nodes = this.visable_.nodes;
1414514f5e3Sopenharmony_ci    let lines = this.visable_.lines;
1424514f5e3Sopenharmony_ci    let hideChanged = false;
1434514f5e3Sopenharmony_ci    for (let l of lines) {
1444514f5e3Sopenharmony_ci      let n1 = nodes[l.fromId];
1454514f5e3Sopenharmony_ci      let n2 = nodes[l.toId];
1464514f5e3Sopenharmony_ci
1474514f5e3Sopenharmony_ci      let id1 = parseInt(n1.ir.id);
1484514f5e3Sopenharmony_ci      let id2 = parseInt(n2.ir.id);
1494514f5e3Sopenharmony_ci      let idx = -1;
1504514f5e3Sopenharmony_ci      if (type === 0 && (n1.mask & this.mask_) !== 0 && this.selectPoint_.indexOf(id2) >= 0) { //选中前继
1514514f5e3Sopenharmony_ci        idx = this.hideNodeIds_.indexOf(id1);
1524514f5e3Sopenharmony_ci        sel.add(id1);
1534514f5e3Sopenharmony_ci      }
1544514f5e3Sopenharmony_ci      if (type === 1 && (n2.mask & this.mask_) !== 0 && this.selectPoint_.indexOf(id1) >= 0) { //选中后继
1554514f5e3Sopenharmony_ci        idx = this.hideNodeIds_.indexOf(id2);
1564514f5e3Sopenharmony_ci        sel.add(id2);
1574514f5e3Sopenharmony_ci      }
1584514f5e3Sopenharmony_ci      if (idx >= 0) {
1594514f5e3Sopenharmony_ci        this.hideNodeIds_.splice(idx, 1);
1604514f5e3Sopenharmony_ci        hideChanged = true;
1614514f5e3Sopenharmony_ci      }
1624514f5e3Sopenharmony_ci    }
1634514f5e3Sopenharmony_ci    this.selectPoint_ = [...sel];
1644514f5e3Sopenharmony_ci    if (hideChanged) {
1654514f5e3Sopenharmony_ci      this.changeVisable();
1664514f5e3Sopenharmony_ci    }
1674514f5e3Sopenharmony_ci  }
1684514f5e3Sopenharmony_ci  loading() {
1694514f5e3Sopenharmony_ci    if (this.loaded_) {
1704514f5e3Sopenharmony_ci      return false;
1714514f5e3Sopenharmony_ci    }
1724514f5e3Sopenharmony_ci    if (this.parser_.parsing()) {
1734514f5e3Sopenharmony_ci      return true;
1744514f5e3Sopenharmony_ci    }
1754514f5e3Sopenharmony_ci    if (!this.inited_) {
1764514f5e3Sopenharmony_ci      this.inited_ = true;
1774514f5e3Sopenharmony_ci      this.InitViewer(this.parser_.output_);
1784514f5e3Sopenharmony_ci      return true;
1794514f5e3Sopenharmony_ci    }
1804514f5e3Sopenharmony_ci    let total = 1;
1814514f5e3Sopenharmony_ci    let procto = 1;
1824514f5e3Sopenharmony_ci    let loadonce = 1;
1834514f5e3Sopenharmony_ci    for (let file in this.data_) {
1844514f5e3Sopenharmony_ci      for (let func in this.data_[file]) {
1854514f5e3Sopenharmony_ci        for (let method of this.data_[file][func]) {
1864514f5e3Sopenharmony_ci          total++;
1874514f5e3Sopenharmony_ci          if (method.loaded) {
1884514f5e3Sopenharmony_ci            procto++;
1894514f5e3Sopenharmony_ci            continue;
1904514f5e3Sopenharmony_ci          }
1914514f5e3Sopenharmony_ci          if (loadonce <= 0) {
1924514f5e3Sopenharmony_ci            continue;
1934514f5e3Sopenharmony_ci          }
1944514f5e3Sopenharmony_ci          loadonce--;
1954514f5e3Sopenharmony_ci
1964514f5e3Sopenharmony_ci          method.irAll = IrToPicture.toPicture(method.irList, 1, method.type.startsWith('block:'));
1974514f5e3Sopenharmony_ci          method.loaded = true;
1984514f5e3Sopenharmony_ci        }
1994514f5e3Sopenharmony_ci      }
2004514f5e3Sopenharmony_ci    }
2014514f5e3Sopenharmony_ci    if (loadonce === 0) {
2024514f5e3Sopenharmony_ci      XTools.PROC_TO = 20 + procto / total * 80;
2034514f5e3Sopenharmony_ci      return true;
2044514f5e3Sopenharmony_ci    }
2054514f5e3Sopenharmony_ci    XTools.PROC_TO = 100;
2064514f5e3Sopenharmony_ci    this.loaded_ = true;
2074514f5e3Sopenharmony_ci    this.changeFile(this.pointFile_);
2084514f5e3Sopenharmony_ci    NapiLog.logInfo('load cost', Date.now() - this.t1_);
2094514f5e3Sopenharmony_ci    return true;
2104514f5e3Sopenharmony_ci  }
2114514f5e3Sopenharmony_ci  changeFile(name) {
2124514f5e3Sopenharmony_ci    this.pointFile_ = name;
2134514f5e3Sopenharmony_ci    let funcs = Object.keys(this.data_[this.pointFile_]);
2144514f5e3Sopenharmony_ci    this.selectFunc_.resetList(funcs, funcs[0]);
2154514f5e3Sopenharmony_ci    this.changeFunc(funcs[0]);
2164514f5e3Sopenharmony_ci  }
2174514f5e3Sopenharmony_ci  changeFunc(name) {
2184514f5e3Sopenharmony_ci    this.pointFunc_ = name;
2194514f5e3Sopenharmony_ci    let methods = [];
2204514f5e3Sopenharmony_ci    for (let i = 0; i < this.data_[this.pointFile_][this.pointFunc_].length; i++) {
2214514f5e3Sopenharmony_ci      methods.push((i + 1) + ',' + this.data_[this.pointFile_][this.pointFunc_][i].type);
2224514f5e3Sopenharmony_ci    }
2234514f5e3Sopenharmony_ci    this.selectMethod_.resetList(methods, methods[0]);
2244514f5e3Sopenharmony_ci    this.changeMethod(methods[0]);
2254514f5e3Sopenharmony_ci  }
2264514f5e3Sopenharmony_ci  changeMethod(name) {
2274514f5e3Sopenharmony_ci    this.pointMethod_ = name;
2284514f5e3Sopenharmony_ci    let p = parseInt(name.split(',')[0]) - 1;
2294514f5e3Sopenharmony_ci    this.direct_ = this.data_[this.pointFile_][this.pointFunc_][p];
2304514f5e3Sopenharmony_ci    this.changeVisable();
2314514f5e3Sopenharmony_ci  }
2324514f5e3Sopenharmony_ci  changeVisable() {
2334514f5e3Sopenharmony_ci    this.visable_ = this.direct_.irAll;
2344514f5e3Sopenharmony_ci    let nodes = this.visable_.nodes;
2354514f5e3Sopenharmony_ci    let lines = this.visable_.lines;
2364514f5e3Sopenharmony_ci
2374514f5e3Sopenharmony_ci    let showNodes = [];
2384514f5e3Sopenharmony_ci    for (let k in nodes) {
2394514f5e3Sopenharmony_ci      let n = nodes[k];
2404514f5e3Sopenharmony_ci      if (this.hideNodeIds_.indexOf(parseInt(n.ir.id)) >= 0) {
2414514f5e3Sopenharmony_ci        n.hide = true;
2424514f5e3Sopenharmony_ci      }
2434514f5e3Sopenharmony_ci      else {
2444514f5e3Sopenharmony_ci        n.hide = (n.mask & this.mask_) === 0;
2454514f5e3Sopenharmony_ci        if (!n.hide) {
2464514f5e3Sopenharmony_ci          showNodes.push(k);
2474514f5e3Sopenharmony_ci        }
2484514f5e3Sopenharmony_ci      }
2494514f5e3Sopenharmony_ci    }
2504514f5e3Sopenharmony_ci    for (let k of showNodes) {
2514514f5e3Sopenharmony_ci      let n = nodes[k];
2524514f5e3Sopenharmony_ci      for (let i = 0; i < 5; i++) {
2534514f5e3Sopenharmony_ci        if ((this.mask_ & (1 << i) !== 0) && (n.mask & (1 << i) !== 0)) { //进入点也加进来
2544514f5e3Sopenharmony_ci          for (let id of n.ir.in[i]) {
2554514f5e3Sopenharmony_ci            nodes[id].hide = false;
2564514f5e3Sopenharmony_ci          }
2574514f5e3Sopenharmony_ci        }
2584514f5e3Sopenharmony_ci      }
2594514f5e3Sopenharmony_ci    }
2604514f5e3Sopenharmony_ci    for (let k in nodes) {
2614514f5e3Sopenharmony_ci      let n = nodes[k];
2624514f5e3Sopenharmony_ci      if (this.hideNodeIds_.indexOf(parseInt(n.ir.id)) >= 0) {
2634514f5e3Sopenharmony_ci        n.hide = true;
2644514f5e3Sopenharmony_ci      }
2654514f5e3Sopenharmony_ci    }
2664514f5e3Sopenharmony_ci    this.scrollY_.setBarOff(0);
2674514f5e3Sopenharmony_ci    this.scrollX_.setBarOff(0.5);
2684514f5e3Sopenharmony_ci  }
2694514f5e3Sopenharmony_ci  makeLevely(nodes) {
2704514f5e3Sopenharmony_ci    let levely = new Set();
2714514f5e3Sopenharmony_ci    for (let k in nodes) {
2724514f5e3Sopenharmony_ci      let n = nodes[k];
2734514f5e3Sopenharmony_ci      if (n.hide) {
2744514f5e3Sopenharmony_ci        continue;
2754514f5e3Sopenharmony_ci      }
2764514f5e3Sopenharmony_ci      if (n.deep !== IrToPicture.INVALID_DEEP) {
2774514f5e3Sopenharmony_ci        levely.add(n.pos.y);
2784514f5e3Sopenharmony_ci      }
2794514f5e3Sopenharmony_ci    }
2804514f5e3Sopenharmony_ci    return Array.from(levely).sort((a, b) => { return parseInt(a) - parseInt(b) });
2814514f5e3Sopenharmony_ci  }
2824514f5e3Sopenharmony_ci  drawSmallMap(nodes, x1, x2, y1, y2) {
2834514f5e3Sopenharmony_ci    if (x1 === x2 || y2 === y1) {
2844514f5e3Sopenharmony_ci      return;
2854514f5e3Sopenharmony_ci    }
2864514f5e3Sopenharmony_ci    let [tx, ty, w, h] = this.smallMapRect;
2874514f5e3Sopenharmony_ci    X2DFast.gi().fillRect(tx, ty, w, h, 0x80000000);
2884514f5e3Sopenharmony_ci
2894514f5e3Sopenharmony_ci    let sw = w / (x2 - x1);
2904514f5e3Sopenharmony_ci    let sh = h / (y2 - y1);
2914514f5e3Sopenharmony_ci
2924514f5e3Sopenharmony_ci    let dh = Math.max(20 * sh, 1);
2934514f5e3Sopenharmony_ci    for (let k in nodes) { //画节点
2944514f5e3Sopenharmony_ci      let n = nodes[k];
2954514f5e3Sopenharmony_ci      if (n.hide) {
2964514f5e3Sopenharmony_ci        continue;
2974514f5e3Sopenharmony_ci      }
2984514f5e3Sopenharmony_ci      let dx = n.pos.x - x1;
2994514f5e3Sopenharmony_ci      let dy = n.pos.y - y1;
3004514f5e3Sopenharmony_ci      let dw = Math.max((n.nameWidth + 6) * sw, 1);
3014514f5e3Sopenharmony_ci      if (this.selectPoint_.indexOf(parseInt(k)) >= 0) {
3024514f5e3Sopenharmony_ci        if (this.drapSelect_) {
3034514f5e3Sopenharmony_ci          dx += this.drapSelect_.dx;
3044514f5e3Sopenharmony_ci          dy += this.drapSelect_.dy;
3054514f5e3Sopenharmony_ci        }
3064514f5e3Sopenharmony_ci        X2DFast.gi().fillRect(tx + (dx - 3) * sw, ty + (dy - 10) * sh, dw, dh, 0xff000000);
3074514f5e3Sopenharmony_ci      }
3084514f5e3Sopenharmony_ci      else {
3094514f5e3Sopenharmony_ci        let selectWith = false;
3104514f5e3Sopenharmony_ci        for (let inl of n.in) {
3114514f5e3Sopenharmony_ci          if (this.selectPoint_.indexOf(parseInt(inl.fromId)) >= 0) {
3124514f5e3Sopenharmony_ci            selectWith = true;
3134514f5e3Sopenharmony_ci            break;
3144514f5e3Sopenharmony_ci          }
3154514f5e3Sopenharmony_ci        }
3164514f5e3Sopenharmony_ci        if (!selectWith) {
3174514f5e3Sopenharmony_ci          for (let outl of n.out) {
3184514f5e3Sopenharmony_ci            if (this.selectPoint_.indexOf(parseInt(outl.toId)) >= 0) {
3194514f5e3Sopenharmony_ci              selectWith = true;
3204514f5e3Sopenharmony_ci              break;
3214514f5e3Sopenharmony_ci            }
3224514f5e3Sopenharmony_ci          }
3234514f5e3Sopenharmony_ci        }
3244514f5e3Sopenharmony_ci        if (selectWith) {
3254514f5e3Sopenharmony_ci          X2DFast.gi().fillRect(tx + (dx - 3) * sw, ty + (dy - 10) * sh, dw, dh, 0xff000000);
3264514f5e3Sopenharmony_ci        }
3274514f5e3Sopenharmony_ci        else {
3284514f5e3Sopenharmony_ci          X2DFast.gi().fillRect(tx + (dx - 3) * sw, ty + (dy - 10) * sh, dw, dh, XTools.CONFIG.NodeColor[n.type]);
3294514f5e3Sopenharmony_ci        }
3304514f5e3Sopenharmony_ci      }
3314514f5e3Sopenharmony_ci    }
3324514f5e3Sopenharmony_ci    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);
3334514f5e3Sopenharmony_ci  }
3344514f5e3Sopenharmony_ci  onDraw() {
3354514f5e3Sopenharmony_ci    if (this.loading()) {
3364514f5e3Sopenharmony_ci      X2DFast.gi().drawText('Loading ' + XTools.PROC_TO.toFixed(1) + '%', 20, Scr.logicw / 2, Scr.logich / 2, 1, 1, 0, -2, -2, 0xff000000);
3374514f5e3Sopenharmony_ci      return;
3384514f5e3Sopenharmony_ci    }
3394514f5e3Sopenharmony_ci    let smallMapSize = parseInt(Math.min(Scr.logicw / 3, Scr.logich / 3));
3404514f5e3Sopenharmony_ci    this.smallMapRect = [Scr.logicw - 50 - smallMapSize, 50, smallMapSize, smallMapSize];
3414514f5e3Sopenharmony_ci    let nodes = this.visable_.nodes;
3424514f5e3Sopenharmony_ci    let lines = this.visable_.lines;
3434514f5e3Sopenharmony_ci    let levely = this.makeLevely(nodes);
3444514f5e3Sopenharmony_ci    let maxx = -9999;
3454514f5e3Sopenharmony_ci    let minx = 9999;
3464514f5e3Sopenharmony_ci    let mouseOn = -1;
3474514f5e3Sopenharmony_ci    let collect = {
3484514f5e3Sopenharmony_ci      singleCount: 0,
3494514f5e3Sopenharmony_ci      showCount: 0,
3504514f5e3Sopenharmony_ci      nodeCount: Object.keys(nodes).length,
3514514f5e3Sopenharmony_ci    };
3524514f5e3Sopenharmony_ci    for (let k in nodes) {
3534514f5e3Sopenharmony_ci      let n = nodes[k];
3544514f5e3Sopenharmony_ci      if (n.hide) {
3554514f5e3Sopenharmony_ci        continue;
3564514f5e3Sopenharmony_ci      }
3574514f5e3Sopenharmony_ci      collect.showCount++;
3584514f5e3Sopenharmony_ci      if (n.deep !== IrToPicture.INVALID_DEEP) {
3594514f5e3Sopenharmony_ci        collect.singleCount++;
3604514f5e3Sopenharmony_ci        if (maxx < n.pos.x + n.nameWidth + this.offx_) {
3614514f5e3Sopenharmony_ci          maxx = n.pos.x + n.nameWidth + this.offx_;
3624514f5e3Sopenharmony_ci        }
3634514f5e3Sopenharmony_ci        if (minx > n.pos.x + this.offx_) {
3644514f5e3Sopenharmony_ci          minx = n.pos.x + this.offx_;
3654514f5e3Sopenharmony_ci        }
3664514f5e3Sopenharmony_ci      }
3674514f5e3Sopenharmony_ci      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)) {
3684514f5e3Sopenharmony_ci        mouseOn = k;
3694514f5e3Sopenharmony_ci      }
3704514f5e3Sopenharmony_ci      n.outhx = {};
3714514f5e3Sopenharmony_ci    }
3724514f5e3Sopenharmony_ci    this.selectLines_ = [];
3734514f5e3Sopenharmony_ci    let mmx1 = this.drawLines(this.offx_, this.offy_, nodes, lines, levely, [minx - 20, maxx + 20], false); //未选中的线
3744514f5e3Sopenharmony_ci    for (let k in nodes) { //画节点
3754514f5e3Sopenharmony_ci      let n = nodes[k];
3764514f5e3Sopenharmony_ci      if (n.deep === IrToPicture.INVALID_DEEP) {
3774514f5e3Sopenharmony_ci        if (n.pos.x === IrToPicture.INVALID_DEEP) {
3784514f5e3Sopenharmony_ci          n.pos.x = mmx1[1] - this.offx_ + 20;
3794514f5e3Sopenharmony_ci        }
3804514f5e3Sopenharmony_ci      }
3814514f5e3Sopenharmony_ci      if (n.hide) {
3824514f5e3Sopenharmony_ci        continue;
3834514f5e3Sopenharmony_ci      }
3844514f5e3Sopenharmony_ci      let dx = n.pos.x + this.offx_;
3854514f5e3Sopenharmony_ci      let dy = n.pos.y + this.offy_;
3864514f5e3Sopenharmony_ci      if (this.selectPoint_.indexOf(parseInt(k)) >= 0) {
3874514f5e3Sopenharmony_ci        if (this.drapSelect_) {
3884514f5e3Sopenharmony_ci          dx += this.drapSelect_.dx;
3894514f5e3Sopenharmony_ci          dy += this.drapSelect_.dy;
3904514f5e3Sopenharmony_ci        }
3914514f5e3Sopenharmony_ci        X2DFast.gi().fillRect(dx - 3, dy - 10, n.nameWidth + 6, 20, 0xffffff00);
3924514f5e3Sopenharmony_ci        X2DFast.gi().drawRect(dx - 3, dy - 10, n.nameWidth + 6, 20, 0xff000000, 2);
3934514f5e3Sopenharmony_ci      }
3944514f5e3Sopenharmony_ci      else {
3954514f5e3Sopenharmony_ci        X2DFast.gi().fillRect(dx - 3, dy - 10, n.nameWidth + 6, 20, XTools.CONFIG.NodeColor[n.type]);
3964514f5e3Sopenharmony_ci        let selectWith = false;
3974514f5e3Sopenharmony_ci        for (let inl of n.in) {
3984514f5e3Sopenharmony_ci          if (this.selectPoint_.indexOf(parseInt(inl.fromId)) >= 0) {
3994514f5e3Sopenharmony_ci            selectWith = true;
4004514f5e3Sopenharmony_ci            break;
4014514f5e3Sopenharmony_ci          }
4024514f5e3Sopenharmony_ci        }
4034514f5e3Sopenharmony_ci        if (!selectWith) {
4044514f5e3Sopenharmony_ci          for (let outl of n.out) {
4054514f5e3Sopenharmony_ci            if (this.selectPoint_.indexOf(parseInt(outl.toId)) >= 0) {
4064514f5e3Sopenharmony_ci              selectWith = true;
4074514f5e3Sopenharmony_ci              break;
4084514f5e3Sopenharmony_ci            }
4094514f5e3Sopenharmony_ci          }
4104514f5e3Sopenharmony_ci        }
4114514f5e3Sopenharmony_ci        if (selectWith) {
4124514f5e3Sopenharmony_ci          X2DFast.gi().drawRect(dx - 3, dy - 10, n.nameWidth + 6, 20, 0xff000000, 2);
4134514f5e3Sopenharmony_ci        }
4144514f5e3Sopenharmony_ci      }
4154514f5e3Sopenharmony_ci      X2DFast.gi().drawText(n.name, 14, dx + n.nameWidth / 2, dy + 2, 1, 1, 0, -2, -2, 0xff000000);
4164514f5e3Sopenharmony_ci    }
4174514f5e3Sopenharmony_ci    this.drawLines(this.offx_, this.offy_, nodes, lines, levely, [minx - 20, maxx + 20], true); //选中的线
4184514f5e3Sopenharmony_ci    for (let ln of this.selectLines_) {
4194514f5e3Sopenharmony_ci      let [r, g, b, a] = XTexture.ExpandColor(ln[4]);
4204514f5e3Sopenharmony_ci      r = Math.max(0, r * 255 - 32);
4214514f5e3Sopenharmony_ci      g = Math.max(0, g * 255 - 32);
4224514f5e3Sopenharmony_ci      b = Math.max(0, b * 255 - 32);
4234514f5e3Sopenharmony_ci      this.drawLine(ln[0], ln[1], ln[2], ln[3], 0xff000000 | (r << 16) | (g << 8) | b, ln[5] + 1);
4244514f5e3Sopenharmony_ci    }
4254514f5e3Sopenharmony_ci    if (mouseOn >= 0) {
4264514f5e3Sopenharmony_ci      let n = nodes[mouseOn]; //显示选中节点的信息
4274514f5e3Sopenharmony_ci      let w = n.ir.maxDetailWidth + 2;
4284514f5e3Sopenharmony_ci      let h = n.ir.detailList.length * 16 + 2;
4294514f5e3Sopenharmony_ci      let x = XTools.MOUSE_POS.x - w;
4304514f5e3Sopenharmony_ci      let y = XTools.MOUSE_POS.y - h;
4314514f5e3Sopenharmony_ci      if (x < 10) {
4324514f5e3Sopenharmony_ci        x = 10;
4334514f5e3Sopenharmony_ci      }
4344514f5e3Sopenharmony_ci      if (y < 130) {
4354514f5e3Sopenharmony_ci        y = 130;
4364514f5e3Sopenharmony_ci      }
4374514f5e3Sopenharmony_ci
4384514f5e3Sopenharmony_ci      X2DFast.gi().fillRect(x, y, w, h, (XTools.CONFIG.NodeColor[n.type] & 0xffffff) | 0xC0000000);
4394514f5e3Sopenharmony_ci
4404514f5e3Sopenharmony_ci      for (let i = 0; i < n.ir.detailList.length; i++) {
4414514f5e3Sopenharmony_ci        X2DFast.gi().drawText(n.ir.detailList[i], 14, x + 1, y + 1 + i * 16, 1, 1, 0, -1, -1, 0xff000000);
4424514f5e3Sopenharmony_ci      }
4434514f5e3Sopenharmony_ci    }
4444514f5e3Sopenharmony_ci
4454514f5e3Sopenharmony_ci    for (let btn of this.btnGo_) {
4464514f5e3Sopenharmony_ci      btn.draw();
4474514f5e3Sopenharmony_ci    }
4484514f5e3Sopenharmony_ci
4494514f5e3Sopenharmony_ci    let x1 = 9999;
4504514f5e3Sopenharmony_ci    let y1 = 9999;
4514514f5e3Sopenharmony_ci    let x2 = -9999;
4524514f5e3Sopenharmony_ci    let y2 = -9999;
4534514f5e3Sopenharmony_ci    for (let k in nodes) {
4544514f5e3Sopenharmony_ci      let n = nodes[k];
4554514f5e3Sopenharmony_ci      if (n.hide) {
4564514f5e3Sopenharmony_ci        continue;
4574514f5e3Sopenharmony_ci      }
4584514f5e3Sopenharmony_ci      if (n.pos.x < x1) {
4594514f5e3Sopenharmony_ci        x1 = n.pos.x;
4604514f5e3Sopenharmony_ci      }
4614514f5e3Sopenharmony_ci      if (n.pos.x + n.nameWidth > x2) {
4624514f5e3Sopenharmony_ci        x2 = n.pos.x + n.nameWidth;
4634514f5e3Sopenharmony_ci      }
4644514f5e3Sopenharmony_ci
4654514f5e3Sopenharmony_ci      if (n.pos.y < y1) {
4664514f5e3Sopenharmony_ci        y1 = n.pos.y;
4674514f5e3Sopenharmony_ci      }
4684514f5e3Sopenharmony_ci      if (n.pos.y + n.nameWidth > y2) {
4694514f5e3Sopenharmony_ci        y2 = n.pos.y + IrToPicture.NODEH;
4704514f5e3Sopenharmony_ci      }
4714514f5e3Sopenharmony_ci    }
4724514f5e3Sopenharmony_ci    x1 = Math.min(mmx1[0] - this.offx_, x1) - Scr.logicw / 3;
4734514f5e3Sopenharmony_ci    x2 = Math.max(mmx1[1] - this.offx_, x2) + Scr.logicw / 3;
4744514f5e3Sopenharmony_ci    y1 = y1 - Scr.logich / 3;
4754514f5e3Sopenharmony_ci    y2 = y2 + Scr.logich / 3;
4764514f5e3Sopenharmony_ci    this.dragScoll = {
4774514f5e3Sopenharmony_ci      x1: x1,
4784514f5e3Sopenharmony_ci      x2: x2,
4794514f5e3Sopenharmony_ci      y1: y1,
4804514f5e3Sopenharmony_ci      y2: y2,
4814514f5e3Sopenharmony_ci    };
4824514f5e3Sopenharmony_ci    let scrollW = x2 - x1;
4834514f5e3Sopenharmony_ci    let scrollH = y2 - y1;
4844514f5e3Sopenharmony_ci    this.dragScoll.hh = scrollH - Scr.logich;
4854514f5e3Sopenharmony_ci    this.dragScoll.ww = scrollW - Scr.logicw;
4864514f5e3Sopenharmony_ci    if (this.dragScoll.hh < 1) {
4874514f5e3Sopenharmony_ci      this.dragScoll.hh = 1;
4884514f5e3Sopenharmony_ci    }
4894514f5e3Sopenharmony_ci    if (this.dragScoll.ww < 1) {
4904514f5e3Sopenharmony_ci      this.dragScoll.ww = 1;
4914514f5e3Sopenharmony_ci    }
4924514f5e3Sopenharmony_ci    if (this.drapBackground_) {
4934514f5e3Sopenharmony_ci      this.scrollY_.setBarOff(-(this.offy_ + this.dragScoll.y1) / this.dragScoll.hh);
4944514f5e3Sopenharmony_ci      this.scrollX_.setBarOff(-(this.offx_ + this.dragScoll.x1) / this.dragScoll.ww);
4954514f5e3Sopenharmony_ci    }
4964514f5e3Sopenharmony_ci    else {
4974514f5e3Sopenharmony_ci      this.offy_ = (-this.scrollY_.getBarOff()) * this.dragScoll.hh - this.dragScoll.y1;
4984514f5e3Sopenharmony_ci      this.offx_ = (-this.scrollX_.getBarOff()) * this.dragScoll.ww - this.dragScoll.x1;
4994514f5e3Sopenharmony_ci    }
5004514f5e3Sopenharmony_ci    if (this.dragScoll.hh > 1) {
5014514f5e3Sopenharmony_ci      this.scrollY_.move(Scr.logicw - 20, 100, 20, Scr.logich - 100 - 20).draw();
5024514f5e3Sopenharmony_ci    }
5034514f5e3Sopenharmony_ci    if (this.dragScoll.ww > 1) {
5044514f5e3Sopenharmony_ci      this.scrollX_.move(20, Scr.logich - 20, Scr.logicw - 40, 20).draw();
5054514f5e3Sopenharmony_ci    }
5064514f5e3Sopenharmony_ci
5074514f5e3Sopenharmony_ci    this.drawSmallMap(nodes, x1, x2, y1, y2);
5084514f5e3Sopenharmony_ci
5094514f5e3Sopenharmony_ci    if (this.searchInput) {
5104514f5e3Sopenharmony_ci      let x = this.searchInput.pos[0];
5114514f5e3Sopenharmony_ci      let y = this.searchInput.pos[1];
5124514f5e3Sopenharmony_ci      let w = this.searchInput.pos[2];
5134514f5e3Sopenharmony_ci      let h = this.searchInput.pos[3];
5144514f5e3Sopenharmony_ci      X2DFast.gi().fillRect(x, y, w, h, 0x80000000);
5154514f5e3Sopenharmony_ci
5164514f5e3Sopenharmony_ci      let searchResultTxt =
5174514f5e3Sopenharmony_ci        this.searchInput.result.length === 0 ? '0/0' :
5184514f5e3Sopenharmony_ci          this.searchInput.point + 1 + '/' + this.searchInput.result.length;
5194514f5e3Sopenharmony_ci
5204514f5e3Sopenharmony_ci      this.searchInput.btnUp.move(x + 20, y + 50, 32, 24).draw();
5214514f5e3Sopenharmony_ci
5224514f5e3Sopenharmony_ci      X2DFast.gi().drawText(
5234514f5e3Sopenharmony_ci        searchResultTxt,
5244514f5e3Sopenharmony_ci        20,
5254514f5e3Sopenharmony_ci        x + w / 2,
5264514f5e3Sopenharmony_ci        y + 50 + 12,
5274514f5e3Sopenharmony_ci        1,
5284514f5e3Sopenharmony_ci        1,
5294514f5e3Sopenharmony_ci        0,
5304514f5e3Sopenharmony_ci        -2,
5314514f5e3Sopenharmony_ci        -2,
5324514f5e3Sopenharmony_ci        0xffffffff
5334514f5e3Sopenharmony_ci      ) + 16;
5344514f5e3Sopenharmony_ci
5354514f5e3Sopenharmony_ci      this.searchInput.btnDown.move(x + w - 20 - 32, y + 50, 32, 24).draw();
5364514f5e3Sopenharmony_ci      this.searchInput.btnClose.move(x + w - 40, y + 10, 30, 30).draw();
5374514f5e3Sopenharmony_ci    }
5384514f5e3Sopenharmony_ci  }
5394514f5e3Sopenharmony_ci  checkLevel(levely, n1, n2) {
5404514f5e3Sopenharmony_ci    let i1 = levely.indexOf(n1.pos.y);
5414514f5e3Sopenharmony_ci    let i2 = levely.indexOf(n2.pos.y);
5424514f5e3Sopenharmony_ci    return i1 + 1 === i2;
5434514f5e3Sopenharmony_ci  }
5444514f5e3Sopenharmony_ci  drawLines(offx, offy, nodes, lines, levely, mmx, select) {
5454514f5e3Sopenharmony_ci    let aaa = 5;
5464514f5e3Sopenharmony_ci    if (true) {
5474514f5e3Sopenharmony_ci      aaa = -5;
5484514f5e3Sopenharmony_ci      for (let l of lines) {
5494514f5e3Sopenharmony_ci        let n1 = nodes[l.fromId];
5504514f5e3Sopenharmony_ci        let n2 = nodes[l.toId];
5514514f5e3Sopenharmony_ci        if (n1.hide || n2.hide) {
5524514f5e3Sopenharmony_ci          continue;
5534514f5e3Sopenharmony_ci        }
5544514f5e3Sopenharmony_ci
5554514f5e3Sopenharmony_ci        let lor = n1.pos.x + n2.pos.x < -50 ? 0 : 1;
5564514f5e3Sopenharmony_ci        if (this.checkLevel(levely, n1, n2)) { }
5574514f5e3Sopenharmony_ci        else {
5584514f5e3Sopenharmony_ci          if (!(n1.outh[l.outNum] in n1.outhx)) {
5594514f5e3Sopenharmony_ci            mmx[lor] += lor === 0 ? aaa : -aaa;
5604514f5e3Sopenharmony_ci            n1.outhx[n1.outh[l.outNum]] = mmx[lor];
5614514f5e3Sopenharmony_ci          }
5624514f5e3Sopenharmony_ci        }
5634514f5e3Sopenharmony_ci      }
5644514f5e3Sopenharmony_ci    }
5654514f5e3Sopenharmony_ci    let mmx1 = [mmx[0], mmx[1]];
5664514f5e3Sopenharmony_ci    for (let l of lines) {
5674514f5e3Sopenharmony_ci      let n1 = nodes[l.fromId];
5684514f5e3Sopenharmony_ci      let n2 = nodes[l.toId];
5694514f5e3Sopenharmony_ci      if (n1.hide || n2.hide) {
5704514f5e3Sopenharmony_ci        continue;
5714514f5e3Sopenharmony_ci      }
5724514f5e3Sopenharmony_ci
5734514f5e3Sopenharmony_ci      let x1 = n1.pos.x + n1.nameWidth - 5 + offx - n1.ltypes.indexOf(l.lineType) * 5;
5744514f5e3Sopenharmony_ci      let y1 = n1.pos.y + 10 + offy;
5754514f5e3Sopenharmony_ci      let x2 = n2.pos.x + n2.nameWidth - 5 + offx - l.inNum * 5;
5764514f5e3Sopenharmony_ci      let y2 = n2.pos.y - 10 + offy;
5774514f5e3Sopenharmony_ci      let lor = n1.pos.x + n2.pos.x < -50 ? 0 : 1;
5784514f5e3Sopenharmony_ci
5794514f5e3Sopenharmony_ci      let selected = false;
5804514f5e3Sopenharmony_ci      if (this.selectPoint_.indexOf(l.fromId) >= 0 || this.selectPoint_.indexOf(l.toId) >= 0) {
5814514f5e3Sopenharmony_ci        selected = true;
5824514f5e3Sopenharmony_ci        if (this.drapSelect_) {
5834514f5e3Sopenharmony_ci          if (this.selectPoint_.indexOf(l.fromId) >= 0) {
5844514f5e3Sopenharmony_ci            x1 += this.drapSelect_.dx;
5854514f5e3Sopenharmony_ci            y1 += this.drapSelect_.dy;
5864514f5e3Sopenharmony_ci          }
5874514f5e3Sopenharmony_ci          if (this.selectPoint_.indexOf(l.toId) >= 0) {
5884514f5e3Sopenharmony_ci            x2 += this.drapSelect_.dx;
5894514f5e3Sopenharmony_ci            y2 += this.drapSelect_.dy;
5904514f5e3Sopenharmony_ci          }
5914514f5e3Sopenharmony_ci        }
5924514f5e3Sopenharmony_ci      }
5934514f5e3Sopenharmony_ci
5944514f5e3Sopenharmony_ci      if (select !== selected) {
5954514f5e3Sopenharmony_ci        if (this.checkLevel(levely, n1, n2)) { }
5964514f5e3Sopenharmony_ci        else {
5974514f5e3Sopenharmony_ci          mmx[lor] += lor === 0 ? -aaa : aaa;
5984514f5e3Sopenharmony_ci        }
5994514f5e3Sopenharmony_ci        continue;
6004514f5e3Sopenharmony_ci      }
6014514f5e3Sopenharmony_ci
6024514f5e3Sopenharmony_ci      let c = 0xffc0c0c0;
6034514f5e3Sopenharmony_ci      let lw = 1;
6044514f5e3Sopenharmony_ci
6054514f5e3Sopenharmony_ci      if (selected) { //选中的点进出的线使用指定的颜色,增加线宽
6064514f5e3Sopenharmony_ci        c = XTools.CONFIG.LineColor[l.lineType];
6074514f5e3Sopenharmony_ci        lw = 2;
6084514f5e3Sopenharmony_ci      }
6094514f5e3Sopenharmony_ci      let ls = [];
6104514f5e3Sopenharmony_ci      if (this.checkLevel(levely, n1, n2)) {
6114514f5e3Sopenharmony_ci        ls.push([x1, y1, x1, y1 + n1.outh[l.outNum], c, lw]);
6124514f5e3Sopenharmony_ci        ls.push([x1, y1 + n1.outh[l.outNum], x2, y1 + n1.outh[l.outNum], c, lw]);
6134514f5e3Sopenharmony_ci        ls.push([x2, y1 + n1.outh[l.outNum], x2, y2, c, lw]);
6144514f5e3Sopenharmony_ci      }
6154514f5e3Sopenharmony_ci      else {
6164514f5e3Sopenharmony_ci        let lx = n1.outhx[n1.outh[l.outNum]]; //n1.outhx[l.outNum] 或 mmx[lor]
6174514f5e3Sopenharmony_ci        let ly = n2.inh[l.fromId + l.lineType]; //n2.inh[l.inNum] 或 n2.inh[n1.ir.id]
6184514f5e3Sopenharmony_ci
6194514f5e3Sopenharmony_ci        ls.push([x1, y1, x1, y1 + n1.outh[l.outNum], c, lw]);
6204514f5e3Sopenharmony_ci        ls.push([x1, y1 + n1.outh[l.outNum], lx, y1 + n1.outh[l.outNum], c, lw]);
6214514f5e3Sopenharmony_ci        ls.push([lx, y1 + n1.outh[l.outNum], lx, y2 - ly, c, lw]);
6224514f5e3Sopenharmony_ci        ls.push([lx, y2 - ly, x2, y2 - ly, c, lw]);
6234514f5e3Sopenharmony_ci        ls.push([x2, y2 - ly, x2, y2, c, lw]);
6244514f5e3Sopenharmony_ci        mmx[lor] += lor === 0 ? -aaa : aaa;
6254514f5e3Sopenharmony_ci      }
6264514f5e3Sopenharmony_ci      let mouseOn = false;
6274514f5e3Sopenharmony_ci      for (let ln of ls) {
6284514f5e3Sopenharmony_ci        mouseOn |= this.drawLine(...ln);
6294514f5e3Sopenharmony_ci      }
6304514f5e3Sopenharmony_ci      if (mouseOn) {
6314514f5e3Sopenharmony_ci        this.selectLines_.push(...ls);
6324514f5e3Sopenharmony_ci      }
6334514f5e3Sopenharmony_ci    }
6344514f5e3Sopenharmony_ci    return [Math.min(mmx1[0], mmx[0]), Math.max(mmx1[1], mmx[1])];
6354514f5e3Sopenharmony_ci  }
6364514f5e3Sopenharmony_ci  drawLine(x1, y1, x2, y2, c, lw = 1) {
6374514f5e3Sopenharmony_ci    if (x1 === x2) {
6384514f5e3Sopenharmony_ci      if (y1 > y2) {
6394514f5e3Sopenharmony_ci        [y1, y2] = [y2, y1];
6404514f5e3Sopenharmony_ci      }
6414514f5e3Sopenharmony_ci      X2DFast.px2f.fillRect(x1, y1, lw, y2 - y1 + lw, c);
6424514f5e3Sopenharmony_ci      if (XTools.InRect(XTools.MOUSE_POS.x, XTools.MOUSE_POS.y, x1 - 1, y1, lw + 2, y2 - y1)) {
6434514f5e3Sopenharmony_ci        return true;
6444514f5e3Sopenharmony_ci      }
6454514f5e3Sopenharmony_ci    }
6464514f5e3Sopenharmony_ci    else if (y1 === y2) {
6474514f5e3Sopenharmony_ci      if (x1 > x2) {
6484514f5e3Sopenharmony_ci        [x1, x2] = [x2, x1];
6494514f5e3Sopenharmony_ci      }
6504514f5e3Sopenharmony_ci      X2DFast.px2f.fillRect(x1, y1, x2 - x1, lw, c);
6514514f5e3Sopenharmony_ci      if (XTools.InRect(XTools.MOUSE_POS.x, XTools.MOUSE_POS.y, x1, y1 - 1, x2 - x1, lw + 2)) {
6524514f5e3Sopenharmony_ci        return true;
6534514f5e3Sopenharmony_ci      }
6544514f5e3Sopenharmony_ci    }
6554514f5e3Sopenharmony_ci    else {
6564514f5e3Sopenharmony_ci
6574514f5e3Sopenharmony_ci    }
6584514f5e3Sopenharmony_ci    return false;
6594514f5e3Sopenharmony_ci  }
6604514f5e3Sopenharmony_ci  locateNode(p) {
6614514f5e3Sopenharmony_ci    this.selectPoint_ = [parseInt(p)];
6624514f5e3Sopenharmony_ci    let nodes = this.visable_.nodes;
6634514f5e3Sopenharmony_ci    let n = nodes[p];
6644514f5e3Sopenharmony_ci
6654514f5e3Sopenharmony_ci    this.offx_ = Scr.logicw / 2 - n.pos.x;
6664514f5e3Sopenharmony_ci    this.offy_ = Scr.logich / 2 - n.pos.y;
6674514f5e3Sopenharmony_ci    this.scrollY_.setBarOff(-(this.offy_ + this.dragScoll.y1) / this.dragScoll.hh);
6684514f5e3Sopenharmony_ci    this.scrollX_.setBarOff(-(this.offx_ + this.dragScoll.x1) / this.dragScoll.ww);
6694514f5e3Sopenharmony_ci    this.offy_ = (-this.scrollY_.getBarOff()) * this.dragScoll.hh - this.dragScoll.y1;
6704514f5e3Sopenharmony_ci    this.offx_ = (-this.scrollX_.getBarOff()) * this.dragScoll.ww - this.dragScoll.x1;
6714514f5e3Sopenharmony_ci  }
6724514f5e3Sopenharmony_ci  findNext() {
6734514f5e3Sopenharmony_ci    if (this.searchInput) {
6744514f5e3Sopenharmony_ci      this.searchInput.point += 1;
6754514f5e3Sopenharmony_ci      if (this.searchInput.point >= this.searchInput.result.length) {
6764514f5e3Sopenharmony_ci        this.searchInput.point = 0;
6774514f5e3Sopenharmony_ci      }
6784514f5e3Sopenharmony_ci      this.locateNode(this.searchInput.result[this.searchInput.point]);
6794514f5e3Sopenharmony_ci    }
6804514f5e3Sopenharmony_ci  }
6814514f5e3Sopenharmony_ci  resetOffset(x, y) {
6824514f5e3Sopenharmony_ci    let [tx, ty, w, h] = this.smallMapRect;
6834514f5e3Sopenharmony_ci    let [x1, y1, x2, y2] = [this.dragScoll.x1, this.dragScoll.y1, this.dragScoll.x2, this.dragScoll.y2];
6844514f5e3Sopenharmony_ci    if (x1 === x2 || y1 === y2) {
6854514f5e3Sopenharmony_ci      return;
6864514f5e3Sopenharmony_ci    }
6874514f5e3Sopenharmony_ci    let sw = w / (x2 - x1);
6884514f5e3Sopenharmony_ci    let sh = h / (y2 - y1);
6894514f5e3Sopenharmony_ci    this.offx_ = (tx - x + Scr.logicw * sw / 2) / sw - x1;
6904514f5e3Sopenharmony_ci    this.offy_ = (ty - y + Scr.logich * sh / 2) / sh - y1;
6914514f5e3Sopenharmony_ci    this.scrollY_.setBarOff(-(this.offy_ + this.dragScoll.y1) / this.dragScoll.hh);
6924514f5e3Sopenharmony_ci    this.scrollX_.setBarOff(-(this.offx_ + this.dragScoll.x1) / this.dragScoll.ww);
6934514f5e3Sopenharmony_ci    this.offy_ = (-this.scrollY_.getBarOff()) * this.dragScoll.hh - this.dragScoll.y1;
6944514f5e3Sopenharmony_ci    this.offx_ = (-this.scrollX_.getBarOff()) * this.dragScoll.ww - this.dragScoll.x1;
6954514f5e3Sopenharmony_ci  }
6964514f5e3Sopenharmony_ci
6974514f5e3Sopenharmony_ci  checkMsgAndDrapSelect_(msg, x, y){
6984514f5e3Sopenharmony_ci    if (msg === 3 && this.drapSelect_) {
6994514f5e3Sopenharmony_ci      let nodes = this.visable_.nodes;
7004514f5e3Sopenharmony_ci      for (let k of this.selectPoint_) {
7014514f5e3Sopenharmony_ci        nodes[k].pos.x += this.drapSelect_.dx;
7024514f5e3Sopenharmony_ci        nodes[k].pos.y += this.drapSelect_.dy;
7034514f5e3Sopenharmony_ci      }
7044514f5e3Sopenharmony_ci      this.drapSelect_ = null;
7054514f5e3Sopenharmony_ci    }
7064514f5e3Sopenharmony_ci  }
7074514f5e3Sopenharmony_ci
7084514f5e3Sopenharmony_ci  checkDrapBackground_(msg, x, y){
7094514f5e3Sopenharmony_ci    if (this.drapBackground_) {
7104514f5e3Sopenharmony_ci      if (msg === 2) {
7114514f5e3Sopenharmony_ci        this.offx_ -= this.drapBackground_.x - x;
7124514f5e3Sopenharmony_ci        this.offy_ -= this.drapBackground_.y - y;
7134514f5e3Sopenharmony_ci        this.drapBackground_.x = x;
7144514f5e3Sopenharmony_ci        this.drapBackground_.y = y;
7154514f5e3Sopenharmony_ci      }
7164514f5e3Sopenharmony_ci      return true;
7174514f5e3Sopenharmony_ci    }
7184514f5e3Sopenharmony_ci  }
7194514f5e3Sopenharmony_ci
7204514f5e3Sopenharmony_ci  checkDrapSelect_(msg, x, y){
7214514f5e3Sopenharmony_ci    if (this.drapSelect_) {
7224514f5e3Sopenharmony_ci      if (msg === 2) {
7234514f5e3Sopenharmony_ci        if (Math.abs(this.drapSelect_.x - x) > 10 ||
7244514f5e3Sopenharmony_ci          Math.abs(this.drapSelect_.y - y) > 10 ||
7254514f5e3Sopenharmony_ci          this.drapSelect_.dx !== 0 ||
7264514f5e3Sopenharmony_ci          this.drapSelect_.dy !== 0) {
7274514f5e3Sopenharmony_ci          this.drapSelect_.dx -= this.drapSelect_.x - x;
7284514f5e3Sopenharmony_ci          this.drapSelect_.dy -= this.drapSelect_.y - y;
7294514f5e3Sopenharmony_ci          this.drapSelect_.x = x;
7304514f5e3Sopenharmony_ci          this.drapSelect_.y = y;
7314514f5e3Sopenharmony_ci        }
7324514f5e3Sopenharmony_ci      }
7334514f5e3Sopenharmony_ci      return true;
7344514f5e3Sopenharmony_ci    }
7354514f5e3Sopenharmony_ci  }
7364514f5e3Sopenharmony_ci
7374514f5e3Sopenharmony_ci  checkSearchInput(msg, x, y){
7384514f5e3Sopenharmony_ci    if (this.searchInput) {
7394514f5e3Sopenharmony_ci      if (XTools.InRect(x, y, ...this.searchInput.pos)) {
7404514f5e3Sopenharmony_ci        if (this.searchInput.btnUp.onTouch(msg, x, y)) {
7414514f5e3Sopenharmony_ci          if (this.searchInput.btnUp.isClicked()) {
7424514f5e3Sopenharmony_ci            this.searchInput.point -= 1;
7434514f5e3Sopenharmony_ci            if (this.searchInput.point < 0) {
7444514f5e3Sopenharmony_ci              this.searchInput.point = this.searchInput.result.length - 1;
7454514f5e3Sopenharmony_ci            }
7464514f5e3Sopenharmony_ci            this.locateNode(this.searchInput.result[this.searchInput.point]);
7474514f5e3Sopenharmony_ci          }
7484514f5e3Sopenharmony_ci        }
7494514f5e3Sopenharmony_ci        if (this.searchInput.btnDown.onTouch(msg, x, y)) {
7504514f5e3Sopenharmony_ci          if (this.searchInput.btnDown.isClicked()) {
7514514f5e3Sopenharmony_ci            this.findNext();
7524514f5e3Sopenharmony_ci          }
7534514f5e3Sopenharmony_ci        }
7544514f5e3Sopenharmony_ci        if (this.searchInput.btnClose.onTouch(msg, x, y)) {
7554514f5e3Sopenharmony_ci          if (this.searchInput.btnClose.isClicked()) {
7564514f5e3Sopenharmony_ci            this.searchInput = null;
7574514f5e3Sopenharmony_ci            CanvasInput.HideEx();
7584514f5e3Sopenharmony_ci          }
7594514f5e3Sopenharmony_ci        }
7604514f5e3Sopenharmony_ci        return true;
7614514f5e3Sopenharmony_ci      }
7624514f5e3Sopenharmony_ci    }
7634514f5e3Sopenharmony_ci  }
7644514f5e3Sopenharmony_ci
7654514f5e3Sopenharmony_ci  checkMsg(msg, x, y){
7664514f5e3Sopenharmony_ci    if (msg === 1) {
7674514f5e3Sopenharmony_ci      let nodes = this.visable_.nodes;
7684514f5e3Sopenharmony_ci      for (let k in nodes) {
7694514f5e3Sopenharmony_ci        let n = nodes[k];
7704514f5e3Sopenharmony_ci        if (n.hide) {
7714514f5e3Sopenharmony_ci          continue;
7724514f5e3Sopenharmony_ci        }
7734514f5e3Sopenharmony_ci        if (XTools.InRect(x, y, n.pos.x + this.offx_ - 3, n.pos.y + this.offy_ - 10, n.nameWidth + 6, 20)) {
7744514f5e3Sopenharmony_ci          if (XTools.KEY_CTRL) {
7754514f5e3Sopenharmony_ci            this.selectPoint_.push(parseInt(k));
7764514f5e3Sopenharmony_ci          }
7774514f5e3Sopenharmony_ci          else {
7784514f5e3Sopenharmony_ci            if (this.selectPoint_.indexOf(parseInt(k)) < 0) {
7794514f5e3Sopenharmony_ci              this.selectPoint_ = [parseInt(k)];
7804514f5e3Sopenharmony_ci            }
7814514f5e3Sopenharmony_ci          }
7824514f5e3Sopenharmony_ci          this.drapSelect_ = {
7834514f5e3Sopenharmony_ci            x: x,
7844514f5e3Sopenharmony_ci            y: y,
7854514f5e3Sopenharmony_ci            dx: 0,
7864514f5e3Sopenharmony_ci            dy: 0,
7874514f5e3Sopenharmony_ci          };
7884514f5e3Sopenharmony_ci          return true;
7894514f5e3Sopenharmony_ci        }
7904514f5e3Sopenharmony_ci      }
7914514f5e3Sopenharmony_ci      this.selectPoint_ = [];
7924514f5e3Sopenharmony_ci    }
7934514f5e3Sopenharmony_ci  }
7944514f5e3Sopenharmony_ci
7954514f5e3Sopenharmony_ci  onTouch(msg, x, y) {
7964514f5e3Sopenharmony_ci    if (this.loading()) {
7974514f5e3Sopenharmony_ci      return true;
7984514f5e3Sopenharmony_ci    }
7994514f5e3Sopenharmony_ci    if (this.smallMapLocked_) {
8004514f5e3Sopenharmony_ci      if (msg === 2) {
8014514f5e3Sopenharmony_ci        this.resetOffset(x, y);
8024514f5e3Sopenharmony_ci      }
8034514f5e3Sopenharmony_ci      if (msg === 3) {
8044514f5e3Sopenharmony_ci        this.smallMapLocked_ = false;
8054514f5e3Sopenharmony_ci      }
8064514f5e3Sopenharmony_ci      return true;
8074514f5e3Sopenharmony_ci    }
8084514f5e3Sopenharmony_ci    if (msg === 6) {
8094514f5e3Sopenharmony_ci      this.drapBackground_ = null;
8104514f5e3Sopenharmony_ci    }
8114514f5e3Sopenharmony_ci    this.checkMsgAndDrapSelect_(msg, x, y)
8124514f5e3Sopenharmony_ci    this.checkDrapBackground_(msg, x, y)
8134514f5e3Sopenharmony_ci    this.checkDrapSelect_(msg, x, y)
8144514f5e3Sopenharmony_ci    if (this.scrollX_.onTouch(msg, x, y)) {
8154514f5e3Sopenharmony_ci      return true;
8164514f5e3Sopenharmony_ci    }
8174514f5e3Sopenharmony_ci    if (this.scrollY_.onTouch(msg, x, y)) {
8184514f5e3Sopenharmony_ci      return true;
8194514f5e3Sopenharmony_ci    }
8204514f5e3Sopenharmony_ci    if (XTools.InRect(x, y, ...this.smallMapRect)) {
8214514f5e3Sopenharmony_ci      if (msg === 1) {
8224514f5e3Sopenharmony_ci        this.resetOffset(x, y);
8234514f5e3Sopenharmony_ci        this.smallMapLocked_ = true;
8244514f5e3Sopenharmony_ci      }
8254514f5e3Sopenharmony_ci      return true;
8264514f5e3Sopenharmony_ci    }
8274514f5e3Sopenharmony_ci    this.checkSearchInput(msg, x, y)
8284514f5e3Sopenharmony_ci    for (let i = this.btnGo_.length - 1; i >= 0; i--) {
8294514f5e3Sopenharmony_ci      if (this.btnGo_[i].onTouch(msg, x, y)) {
8304514f5e3Sopenharmony_ci        return true;
8314514f5e3Sopenharmony_ci      }
8324514f5e3Sopenharmony_ci    }
8334514f5e3Sopenharmony_ci    this.checkMsg(msg, x, y)
8344514f5e3Sopenharmony_ci    if (msg === 4) {
8354514f5e3Sopenharmony_ci      this.drapBackground_ = {
8364514f5e3Sopenharmony_ci        x: x,
8374514f5e3Sopenharmony_ci        y: y,
8384514f5e3Sopenharmony_ci      };
8394514f5e3Sopenharmony_ci    }
8404514f5e3Sopenharmony_ci    return false;
8414514f5e3Sopenharmony_ci  }
8424514f5e3Sopenharmony_ci  onKey(k) {
8434514f5e3Sopenharmony_ci    if (this.loading()) {
8444514f5e3Sopenharmony_ci      return true;
8454514f5e3Sopenharmony_ci    }
8464514f5e3Sopenharmony_ci    if (this.searchInput) {
8474514f5e3Sopenharmony_ci      return true;
8484514f5e3Sopenharmony_ci    }
8494514f5e3Sopenharmony_ci    switch (k) {
8504514f5e3Sopenharmony_ci      case 'PageUp':
8514514f5e3Sopenharmony_ci        this.selectNode(0);
8524514f5e3Sopenharmony_ci        return true;
8534514f5e3Sopenharmony_ci      case 'PageDown':
8544514f5e3Sopenharmony_ci        this.selectNode(1);
8554514f5e3Sopenharmony_ci        return true;
8564514f5e3Sopenharmony_ci      case 'H':
8574514f5e3Sopenharmony_ci      case 'h':
8584514f5e3Sopenharmony_ci        this.hideNode(0);
8594514f5e3Sopenharmony_ci        return true;
8604514f5e3Sopenharmony_ci      case ' ':
8614514f5e3Sopenharmony_ci        this.hideNode(1);
8624514f5e3Sopenharmony_ci        return true;
8634514f5e3Sopenharmony_ci      case 'S':
8644514f5e3Sopenharmony_ci      case 's':
8654514f5e3Sopenharmony_ci        this.hideNode(2);
8664514f5e3Sopenharmony_ci        return true;
8674514f5e3Sopenharmony_ci      case 'Enter':
8684514f5e3Sopenharmony_ci        this.freshNode();
8694514f5e3Sopenharmony_ci        return true;
8704514f5e3Sopenharmony_ci    }
8714514f5e3Sopenharmony_ci    if (k === 'ctrl+f' || k === 'ctrl+F') {
8724514f5e3Sopenharmony_ci      this.searchInput = {
8734514f5e3Sopenharmony_ci        pos: [(Scr.logicw - 300), Scr.logich / 2, 200, 80],
8744514f5e3Sopenharmony_ci        result: [],
8754514f5e3Sopenharmony_ci        point: 0,
8764514f5e3Sopenharmony_ci        btnUp: new XButton(0, 0, 0, 0, '<'),
8774514f5e3Sopenharmony_ci        btnDown: new XButton(0, 0, 0, 0, '>'),
8784514f5e3Sopenharmony_ci        btnClose: new XButton(0, 0, 0, 0, '❌'),
8794514f5e3Sopenharmony_ci      };
8804514f5e3Sopenharmony_ci      let x = this.searchInput.pos[0];
8814514f5e3Sopenharmony_ci      let y = this.searchInput.pos[1];
8824514f5e3Sopenharmony_ci      let w = this.searchInput.pos[2];
8834514f5e3Sopenharmony_ci      let h = this.searchInput.pos[3];
8844514f5e3Sopenharmony_ci      this.searchInput.Open = () => {
8854514f5e3Sopenharmony_ci        CanvasInput.Reset(x, y + 10, w - 32 - 40, 32, '', null, (v) => {
8864514f5e3Sopenharmony_ci          function isRegExp(s) {
8874514f5e3Sopenharmony_ci            try {
8884514f5e3Sopenharmony_ci              new RegExp(s);
8894514f5e3Sopenharmony_ci              return true;
8904514f5e3Sopenharmony_ci            } catch (e) {
8914514f5e3Sopenharmony_ci              return false;
8924514f5e3Sopenharmony_ci            }
8934514f5e3Sopenharmony_ci          }
8944514f5e3Sopenharmony_ci          this.searchInput.result = [];
8954514f5e3Sopenharmony_ci          if (v.length > 0) {
8964514f5e3Sopenharmony_ci            let nodes = this.visable_.nodes;
8974514f5e3Sopenharmony_ci            this.selectPoint_ = [];
8984514f5e3Sopenharmony_ci            for (let i in nodes) {
8994514f5e3Sopenharmony_ci              let n = nodes[i];
9004514f5e3Sopenharmony_ci              let searchName;
9014514f5e3Sopenharmony_ci              if (XTools.CONFIG.OpTypeJsBytecode.indexOf(n.ir.op) >= 0) {
9024514f5e3Sopenharmony_ci                searchName = n.ir.bytecode;
9034514f5e3Sopenharmony_ci              }
9044514f5e3Sopenharmony_ci              else if (n.ir.typedop) {
9054514f5e3Sopenharmony_ci                searchName = n.ir.typedop;
9064514f5e3Sopenharmony_ci              }
9074514f5e3Sopenharmony_ci              else {
9084514f5e3Sopenharmony_ci                searchName = n.ir.op;
9094514f5e3Sopenharmony_ci              }
9104514f5e3Sopenharmony_ci              if (n.ir.id === v || searchName.indexOf(v) >= 0 || (isRegExp(v) && searchName.match(v))) {
9114514f5e3Sopenharmony_ci                this.searchInput.result.push(i);
9124514f5e3Sopenharmony_ci              }
9134514f5e3Sopenharmony_ci            }
9144514f5e3Sopenharmony_ci            if (this.searchInput.result.length > 0) {
9154514f5e3Sopenharmony_ci              this.locateNode(this.searchInput.result[0]);
9164514f5e3Sopenharmony_ci              this.searchInput.point = 0;
9174514f5e3Sopenharmony_ci            }
9184514f5e3Sopenharmony_ci          }
9194514f5e3Sopenharmony_ci        }, this.findNext.bind(this));
9204514f5e3Sopenharmony_ci      };
9214514f5e3Sopenharmony_ci      CanvasInput.SetSafeArea(...this.searchInput.pos);
9224514f5e3Sopenharmony_ci      this.searchInput.Open();
9234514f5e3Sopenharmony_ci    }
9244514f5e3Sopenharmony_ci    return false;
9254514f5e3Sopenharmony_ci  }
9264514f5e3Sopenharmony_ci}
9274514f5e3Sopenharmony_ci
9284514f5e3Sopenharmony_cimodule.exports = {
9294514f5e3Sopenharmony_ci  IrViewer
9304514f5e3Sopenharmony_ci};