1/*
2 * Copyright (c) 2022-2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16const { XMessage } = require('./message/XMessage');
17const { Lexer } = require('./hcs/lexer');
18const { Generator } = require('./hcs/Generator');
19const { Scr } = require('./engine/XDefine');
20const { XButton } = require('./engine/control/XButton');
21const { AttrEditor } = require('./AttrEditor');
22const { NapiLog } = require('./hcs/NapiLog');
23const { XSelect } = require('./engine/control/XSelect');
24const { NodeTools, DataType, NodeType } = require('./hcs/NodeTools');
25const { ModifyNode } = require('./hcs/ModifyNode');
26const { CanvasInput } = require('./hcs/CanvasInput');
27const { RightMenu } = require('./engine/RightMenu');
28const { XTexture } = require('./engine/graphics/XTexture');
29const { XTools } = require('./engine/XTools');
30
31const { ObjectType } = require('./hcs/ast');
32const DISPLAY_TEXT_MAX = 30;
33const ELLIPSIS_LEN = 3;
34const EQUAL_SIGN_LEN = 3;
35const MAX_RANDOM = 255;
36const CONSTANT_MIDDLE = 2;
37const CONSTANT_QUARTER = 4;
38const DRAW_HEIGHT = 4;
39const COLOR_MAX = 10;
40const GRAY_LEVEL = 192;
41const INIT_VALUE = -1;
42const KEY_VALUE_MAX = 30;
43const ONE_KEY_VALUE_MAX = 29;
44const TWO_KEY_VALUE_MAX = 28;
45const THREE_KEY_VALUE_MAX = 27;
46const BGPIC_WIDTH = 156;
47const BGPIC_HEIGHT = 112;
48const DRAWTEXT_OFFSETX = -3;
49const DRAWTEXT_OFFSETY = -3;
50
51const MouseType = {
52  DOWN: 1, // 按下
53  MOVE: 2, // 移动
54  UP: 3, // 抬起
55};
56
57function rgba(colorArr) {
58  return 0xff000000 | (colorArr[0] << 16) | (colorArr[1] << 8) | colorArr[2];
59}
60
61function getDarker(colorArr) {
62  colorArr.forEach((item, index) => {
63    if (item - 0 > COLOR_MAX) {
64      item = item - COLOR_MAX;
65    }
66  });
67  return rgba(colorArr);
68}
69
70function isDarkColor(colorArr) {
71  let grayLevel =
72    colorArr[0] * 0.299 + colorArr[1] * 0.587 + colorArr[2] * 0.114;
73  return grayLevel < GRAY_LEVEL;
74}
75
76function getVsCodeTheme() {
77  MainEditor.CANVAS_BG = 0xff272727;
78  MainEditor.CANVAS_LINE = 0xff000000;
79  MainEditor.NODE_TEXT_COLOR = 0xffffffff;
80  let canvasBg = document.getElementById('canvas_bg');
81  var bgStyle = document.defaultView.getComputedStyle(canvasBg, null);
82  var bgColor = bgStyle.getPropertyValue('background-color').match(/\d{1,3}/g);
83  if (bgColor) {
84    MainEditor.CANVAS_BG = rgba(bgColor);
85    MainEditor.CANVAS_LINE = getDarker(bgColor);
86    MainEditor.IS_DARK_BG = isDarkColor(bgColor);
87    RightMenu.isDarkBackground_ = MainEditor.IS_DARK_BG;
88  }
89
90  var txtColor = bgStyle.getPropertyValue('color').match(/\d{1,3}/g);
91  if (txtColor) {
92    MainEditor.NODE_TEXT_COLOR = rgba(txtColor);
93  }
94}
95
96class MainEditor {
97  constructor() {
98    this.files_ = {};
99    this.nodeCount_ = {};
100    this.filePoint_ = null;
101    this.rootPoint_ = null;
102    this.nodePoint_ = null;
103    this.offX_ = 100;
104    this.offY_ = 100;
105    this.searchKey = null;
106    this.touchQueue_ = [];
107    this.keyQueue_ = [];
108    this.dropAll_ = {
109      locked: false,
110      oldx: INIT_VALUE,
111      oldy: INIT_VALUE,
112    };
113    getVsCodeTheme();
114    this.nodeBtns = [];
115    this.nodeMoreBtns = [];
116    this.nodeBtnPoint_ = 0;
117    this.nodeMoreBtnPoint_ = 0;
118    XMessage.gi().registRecvCallback(this.onReceive);
119    XMessage.gi().send('inited', '');
120    AttrEditor.gi().freshEditor();
121
122    this.sltInclude = new XSelect(['a', 'b', 'c'], 'b');
123    this.sltInclude.registCallback(this.onSelectInclude);
124    NapiLog.registError(this.onError);
125    this.errorMsg_ = [];
126    this.cutImgDict_ = {};
127    this.initMainEditorWithInitValue();
128    this.selectNode_ = {
129      type: null,
130      pnode: null,
131    };
132    this.btnCancelSelect_ = new XButton();
133
134    AttrEditor.gi().registCallback(this.onAttributeChange);
135
136    this.mousePos_ = {
137      x: 0,
138      y: 0,
139    };
140
141    this.whiteImg_ = XTexture.gi().loadTextureFromImage(
142      '../images/rectangle.png'
143    );
144    this.whiteCut_ = XTexture.gi().makeCut(
145      this.whiteImg_,
146      0,
147      0,
148      132,
149      32,
150      132,
151      32
152    );
153    this.cutImgDict_.whiteCut = 'rectangle.png';
154
155    this.cicleImg_ = XTexture.gi().loadTextureFromImage('../images/circle.png');
156    this.circleCut_ = XTexture.gi().makeCut(
157      this.cicleImg_,
158      0,
159      0,
160      20,
161      20,
162      20,
163      20
164    );
165    this.cutImgDict_.circleCut = 'circle.png';
166
167    this.cicleOpenImg_ = XTexture.gi().loadTextureFromImage(
168      '../images/circle_open.png'
169    );
170    this.circleOpenCut_ = XTexture.gi().makeCut(
171      this.cicleOpenImg_,
172      0,
173      0,
174      20,
175      20,
176      20,
177      20
178    );
179    this.cutImgDict_.circleOpenCut = 'circle_open.png';
180
181    this.rectangleFocusImg_ = XTexture.gi().loadTextureFromImage(
182      '../images/rectangle_focus.png'
183    );
184    this.rectangleFocusCut_ = XTexture.gi().makeCut(
185      this.rectangleFocusImg_,
186      0,
187      0,
188      132,
189      32,
190      132,
191      32
192    );
193    this.cutImgDict_['rectangleFocusCut'] = 'rectangle_focus.png';
194
195    this.nodeIconImg_ = XTexture.gi().loadTextureFromImage(
196      '../images/node_icon.png'
197    );
198    this.nodeIconCut_ = XTexture.gi().makeCut(
199      this.nodeIconImg_,
200      0,
201      0,
202      8,
203      8,
204      8,
205      8
206    );
207    this.cutImgDict_['nodeIconCut'] = 'node_icon.png';
208
209    this.attrIconImg_ = XTexture.gi().loadTextureFromImage(
210      '../images/attribute_icon.png'
211    );
212    this.attrIconCut_ = XTexture.gi().makeCut(
213      this.attrIconImg_,
214      0,
215      0,
216      8,
217      8,
218      8,
219      8
220    );
221    this.cutImgDict_['attrIconCut'] = 'attribute_icon.png';
222
223    this.rootIconImg_ = XTexture.gi().loadTextureFromImage(
224      '../images/root_btn.png'
225    );
226    this.rootIconCut_ = XTexture.gi().makeCut(
227      this.rootIconImg_,
228      0,
229      0,
230      132,
231      32,
232      132,
233      32
234    );
235    this.cutImgDict_['rootIconCut'] = 'root_btn.png';
236
237    this.rootIconFocusImg_ = XTexture.gi().loadTextureFromImage(
238      '../images/root_btn_focus.png'
239    );
240    this.rootIconFocusCut_ = XTexture.gi().makeCut(
241      this.rootIconFocusImg_,
242      0,
243      0,
244      132,
245      32,
246      132,
247      32
248    );
249    this.cutImgDict_['rootIconFocusCut'] = 'root_btn_focus.png';
250
251    this.leftRectCicleImg_ = XTexture.gi().loadTextureFromImage(
252      '../images/rectangle.png'
253    );
254    this.leftRectCicleCut_ = XTexture.gi().makeCut(
255      this.leftRectCicleImg_,
256      0,
257      0,
258      8,
259      32,
260      132,
261      32
262    );
263    this.centerRectImg_ = XTexture.gi().loadTextureFromImage(
264      '../images/rectangle.png'
265    );
266    this.centerRectCut_ = XTexture.gi().makeCut(
267      this.centerRectImg_,
268      8,
269      0,
270      116,
271      32,
272      132,
273      32
274    );
275    this.rightRectCicleImg_ = XTexture.gi().loadTextureFromImage(
276      '../images/rectangle.png'
277    );
278    this.rightRectCicleCut_ = XTexture.gi().makeCut(
279      this.rightRectCicleImg_,
280      124,
281      0,
282      8,
283      32,
284      132,
285      32
286    );
287
288    this.leftRectFocusCicleImg_ = XTexture.gi().loadTextureFromImage(
289      '../images/rectangle_focus.png'
290    );
291    this.leftRectFocusCicleCut_ = XTexture.gi().makeCut(
292      this.leftRectFocusCicleImg_,
293      0,
294      0,
295      8,
296      32,
297      132,
298      32
299    );
300    this.centerFocusImg_ = XTexture.gi().loadTextureFromImage(
301      '../images/rectangle_focus.png'
302    );
303    this.centerFocusCut_ = XTexture.gi().makeCut(
304      this.centerFocusImg_,
305      8,
306      0,
307      116,
308      32,
309      132,
310      32
311    );
312    this.rightRectFocusCicleImg_ = XTexture.gi().loadTextureFromImage(
313      '../images/rectangle_focus.png'
314    );
315    this.rightRectFocusCicleCut_ = XTexture.gi().makeCut(
316      this.rightRectFocusCicleImg_,
317      124,
318      0,
319      8,
320      32,
321      132,
322      32
323    );
324
325    this.reloadBgPic();
326
327    RightMenu.popItemFocusImg_ = XTexture.gi().loadTextureFromImage(
328      '../images/pop_item_focus.png'
329    );
330    RightMenu.popItemFocusCut_ = XTexture.gi().makeCut(
331      RightMenu.popItemFocusImg_,
332      0,
333      0,
334      148,
335      32,
336      148,
337      32
338    );
339    this.cutImgDict_['popItemFocusCut'] = 'pop_item_focus.png';
340
341    this.searchBgImg_ = XTexture.gi().loadTextureFromImage(
342      '../images/search_bg.png'
343    );
344    this.searchBgCut_ = XTexture.gi().makeCut(
345      this.searchBgImg_,
346      0,
347      0,
348      494,
349      56,
350      494,
351      56
352    );
353    this.cutImgDict_['searchBgCut'] = 'search_bg.png';
354
355    this.upImg_ = XTexture.gi().loadTextureFromImage(
356      '../images/chevron-up.png'
357    );
358    this.upCut_ = XTexture.gi().makeCut(this.upImg_, 0, 0, 16, 16, 16, 16);
359    this.cutImgDict_['upCut'] = 'chevron-up.png';
360
361    this.downImg_ = XTexture.gi().loadTextureFromImage(
362      '../images/chevron-down.png'
363    );
364    this.downCut_ = XTexture.gi().makeCut(this.downImg_, 0, 0, 16, 16, 16, 16);
365    this.cutImgDict_['downCut'] = 'chevron-down.png';
366
367    this.closeImg_ = XTexture.gi().loadTextureFromImage('../images/close.png');
368    this.closeCut_ = XTexture.gi().makeCut(
369      this.closeImg_,
370      0,
371      0,
372      16,
373      16,
374      16,
375      16
376    );
377    this.cutImgDict_['closeCut'] = 'close.png';
378
379    this.searchImg_ = XTexture.gi().loadTextureFromImage(
380      '../images/search.png'
381    );
382    this.searchCut_ = XTexture.gi().makeCut(
383      this.searchImg_,
384      0,
385      0,
386      16,
387      16,
388      16,
389      16
390    );
391    this.cutImgDict_['searchCut'] = 'search.png';
392
393    this.searchRectFocusCicleImg_ = XTexture.gi().loadTextureFromImage(
394      '../images/search_nood_rect.png'
395    );
396    this.leftSearchFocusCicleCut_ = XTexture.gi().makeCut(
397      this.searchRectFocusCicleImg_,
398      0,
399      0,
400      8,
401      32,
402      132,
403      32
404    );
405    this.centerSearchCut_ = XTexture.gi().makeCut(
406      this.searchRectFocusCicleImg_,
407      8,
408      0,
409      116,
410      32,
411      132,
412      32
413    );
414    this.rightSearchFocusCicleCut_ = XTexture.gi().makeCut(
415      this.searchRectFocusCicleImg_,
416      124,
417      0,
418      8,
419      32,
420      132,
421      32
422    );
423    this.cutImgDict_['searchNoodRectImg'] = 'search_nood_rect.png';
424
425    this.searchAttrCicleImg_ = XTexture.gi().loadTextureFromImage(
426      '../images/search_attr_rect.png'
427    );
428    this.leftSearchAttrCicleCut_ = XTexture.gi().makeCut(
429      this.searchAttrCicleImg_,
430      0,
431      0,
432      8,
433      32,
434      132,
435      32
436    );
437    this.centerSearchAttrCut_ = XTexture.gi().makeCut(
438      this.searchAttrCicleImg_,
439      8,
440      0,
441      116,
442      32,
443      132,
444      32
445    );
446    this.rightSearchAttrCicleCut_ = XTexture.gi().makeCut(
447      this.searchAttrCicleImg_,
448      124,
449      0,
450      8,
451      32,
452      132,
453      32
454    );
455    this.cutImgDict_['searchAttrRectImg'] = 'search_attr_rect.png';
456
457    XMessage.gi().send('cutImgDict', {
458      data: this.cutImgDict_,
459    });
460    this.modifyPos_ = null;
461    this.isFirstDraw = true;
462    this.lenHierarchy = 0;
463
464    this.searchInput = null;
465    this.historyZ = [];
466    this.historyBase = {};
467    this.historyPushed = false;
468  }
469
470  initMainEditorWithInitValue() {
471    this.whiteImg_ = INIT_VALUE;
472    this.whiteCut_ = INIT_VALUE;
473    this.cicleImg_ = INIT_VALUE;
474    this.circleCut_ = INIT_VALUE;
475    this.cicleOpenImg_ = INIT_VALUE;
476    this.circleOpenCut_ = INIT_VALUE;
477    this.rectangleFocusImg_ = INIT_VALUE;
478    this.rectangleFocusCut_ = INIT_VALUE;
479    this.nodeIconImg_ = INIT_VALUE;
480    this.nodeIconCut_ = INIT_VALUE;
481    this.attrIconImg_ = INIT_VALUE;
482    this.attrIconCut_ = INIT_VALUE;
483    this.rootIconImg_ = INIT_VALUE;
484    this.rootIconCut_ = INIT_VALUE;
485    this.rootIconFocusImg_ = INIT_VALUE;
486    this.rootIconFocusCut_ = INIT_VALUE;
487    RightMenu.backgroundImg_ = INIT_VALUE;
488    RightMenu.backgroundCut_ = INIT_VALUE;
489    RightMenu.popItemFocusImg_ = INIT_VALUE;
490    RightMenu.popItemFocusCut_ = INIT_VALUE;
491    this.leftRectCicleCut_ = INIT_VALUE;
492    this.centerRectCut_ = INIT_VALUE;
493    this.rightRectCicleCut_ = INIT_VALUE;
494    this.leftRectFocusCicleCut_ = INIT_VALUE;
495    this.centerFocusCut_ = INIT_VALUE;
496    this.rightRectFocusCicleCut_ = INIT_VALUE;
497    this.delay_ = 0;
498    this.searchBgImg_ = INIT_VALUE;
499    this.searchBgCut_ = INIT_VALUE;
500    this.upImg_ = INIT_VALUE;
501    this.upCut_ = INIT_VALUE;
502    this.downImg_ = INIT_VALUE;
503    this.downCut_ = INIT_VALUE;
504    this.closeImg_ = INIT_VALUE;
505    this.closeCut_ = INIT_VALUE;
506    this.searchImg_ = INIT_VALUE;
507    this.searchCut_ = INIT_VALUE;
508    this.isSearchResult_ = false;
509    this.searchRectFocusCicleImg_ = INIT_VALUE;
510    this.leftSearchFocusCicleCut_ = INIT_VALUE;
511    this.centerSearchCut_ = INIT_VALUE;
512    this.rightSearchFocusCicleCut_ = INIT_VALUE;
513
514    this.searchAttrCicleImg_ = INIT_VALUE;
515    this.leftSearchAttrCicleCut_ = INIT_VALUE;
516    this.centerSearchAttrCut_ = INIT_VALUE;
517    this.rightSearchAttrCicleCut_ = INIT_VALUE;
518  }
519
520  reloadMenuBgPic() {
521    let bgPic = this.reloadBgPic();
522    XMessage.gi().send('reloadMenuBg', {
523      data: bgPic,
524    });
525  }
526
527  reloadBgPic() {
528    let bgPic = RightMenu.isDarkBackground_ ? 'pop_background.png' : 'pop_background_light.png';
529    let bgPicPath = '../images/' + bgPic;
530    RightMenu.backgroundImg_ = XTexture.gi().loadTextureFromImage(bgPicPath);
531    RightMenu.backgroundCut_ = XTexture.gi().makeCut(
532      RightMenu.backgroundImg_,
533      0,
534      0,
535      BGPIC_WIDTH,
536      BGPIC_HEIGHT,
537      BGPIC_WIDTH,
538      BGPIC_HEIGHT
539    );
540    this.cutImgDict_.backgroundCut = bgPic;
541    return bgPic;
542  }
543
544  calcPostionY(data, y) {
545    data.posY = y;
546    let ty = y;
547    switch (data.type_) {
548      case DataType.INT8:
549      case DataType.INT16:
550      case DataType.INT32:
551      case DataType.INT64:
552        y += MainEditor.LINE_HEIGHT;
553        break;
554      case DataType.STRING:
555        y += MainEditor.LINE_HEIGHT;
556        break;
557      case DataType.NODE:
558        if (!data.isOpen_) {
559          y += MainEditor.LINE_HEIGHT;
560        } else {
561          data.value_.forEach((item, index) => {
562            y = this.calcPostionY(item, y);
563          });
564        }
565        break;
566      case DataType.ATTR:
567        y = this.calcPostionY(data.value_, y);
568        break;
569      case DataType.ARRAY:
570        y += MainEditor.LINE_HEIGHT;
571        break;
572      case DataType.REFERENCE:
573        y += MainEditor.LINE_HEIGHT;
574        break;
575      case DataType.DELETE:
576        y += MainEditor.LINE_HEIGHT;
577        break;
578      case DataType.BOOL:
579        y += MainEditor.LINE_HEIGHT;
580        break;
581      default:
582        NapiLog.logError('unknow' + data.type_);
583        break;
584    }
585    if (y > ty) {
586      data.posY = (ty + y - MainEditor.LINE_HEIGHT) / CONSTANT_MIDDLE;
587    }
588    return y > ty + MainEditor.LINE_HEIGHT ? y : ty + MainEditor.LINE_HEIGHT;
589  }
590
591  getNodeText(data) {
592    switch (data.nodeType_) {
593      case NodeType.DATA:
594        return data.name_;
595      case NodeType.DELETE:
596        return data.name_ + ' : delete';
597      case NodeType.TEMPLETE:
598        return 'templete ' + data.name_;
599      case NodeType.INHERIT:
600        if (data.ref_ === 'unknow') {
601          return data.name_;
602        }
603        return data.name_ + ' :: ' + data.ref_;
604      case NodeType.COPY:
605        if (data.ref_ === 'unknow') {
606          return data.name_;
607        }
608        return data.name_ + ' : ' + data.ref_;
609      case NodeType.REFERENCE:
610        if (data.ref_ === 'unknow') {
611          return data.name_;
612        }
613        return data.name_ + ' : &' + data.ref_;
614      default:
615        return 'unknow node type';
616    }
617  }
618
619  drawNode(pm2f, s, size, x, y, type, data) {
620    const SPACE = 2;
621    const MAXLEN_DISPLAY_WITH_SPACE = 25;
622    const MAXLEN_DISPLAY_NO_SPACE = 26;
623    const DISPLAY_TEXT_MAX_NOPOINT = 27;
624    let w = pm2f.getTextWidth(type === DataType.ATTR ? s + ' = ' : s, size);
625    if (data.parent_ === undefined) {
626      return w;
627    }
628
629    if (type === DataType.ATTR) {
630      let lenDisplay = DISPLAY_TEXT_MAX - EQUAL_SIGN_LEN;
631      let orangeColor = 0xffa9a9a9;
632      if (s.length < MAXLEN_DISPLAY_WITH_SPACE) {
633        pm2f.drawText(s, size, x - (data.parent_ !== undefined ? MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_ : 0) +
634          MainEditor.LOGO_LEFT_PADDING + MainEditor.LOGO_SIZE * SPACE,
635        y + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE - MainEditor.NODE_TEXT_SIZE / CONSTANT_MIDDLE, 1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
636        pm2f.drawText(' = ', size, x - (data.parent_ !== undefined ? MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_ : 0) +
637          MainEditor.LOGO_LEFT_PADDING + MainEditor.LOGO_SIZE * SPACE + pm2f.getTextWidth(s, size),
638        y + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE - MainEditor.NODE_TEXT_SIZE / CONSTANT_MIDDLE, 1, 1, 0, 0, 0, orangeColor);
639      } else if (s.length === MAXLEN_DISPLAY_WITH_SPACE) {
640        pm2f.drawText(s, size, x - (data.parent_ !== undefined ? MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_ : 0) +
641          MainEditor.LOGO_LEFT_PADDING + MainEditor.LOGO_SIZE * SPACE,
642        y + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE - MainEditor.NODE_TEXT_SIZE / CONSTANT_MIDDLE, 1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
643        pm2f.drawText(' =', size, x - (data.parent_ !== undefined ? MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_ : 0) +
644          MainEditor.LOGO_LEFT_PADDING + MainEditor.LOGO_SIZE * SPACE + pm2f.getTextWidth(s, size),
645        y + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE - MainEditor.NODE_TEXT_SIZE / CONSTANT_MIDDLE, 1, 1, 0, 0, 0, orangeColor);
646      } else if (s.length === MAXLEN_DISPLAY_NO_SPACE) {
647        pm2f.drawText(s, size, x - (data.parent_ !== undefined ? MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_ : 0) +
648          MainEditor.LOGO_LEFT_PADDING + MainEditor.LOGO_SIZE * SPACE,
649        y + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE - MainEditor.NODE_TEXT_SIZE / CONSTANT_MIDDLE, 1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
650        pm2f.drawText('=', size, x - (data.parent_ !== undefined ? MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_ : 0) +
651          MainEditor.LOGO_LEFT_PADDING + MainEditor.LOGO_SIZE * SPACE + pm2f.getTextWidth(s, size),
652        y + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE - MainEditor.NODE_TEXT_SIZE / CONSTANT_MIDDLE, 1, 1, 0, 0, 0, orangeColor);
653      } else if (s.length > MAXLEN_DISPLAY_NO_SPACE) {
654        s = s.substring(0, lenDisplay) + '...';
655        pm2f.drawText(s, size, x - (data.parent_ !== undefined ? MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_ : 0) +
656          MainEditor.LOGO_LEFT_PADDING + MainEditor.LOGO_SIZE * SPACE,
657        y + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE - MainEditor.NODE_TEXT_SIZE / CONSTANT_MIDDLE, 1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
658      }
659    } else {
660      let logoSizeTimes = 2; // logosize显示大小是logoSize长度的2倍
661      pm2f.drawText( s.length > DISPLAY_TEXT_MAX ? s.substring(0, DISPLAY_TEXT_MAX_NOPOINT) + '...' : s, size, x -
662        (MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_) + MainEditor.LOGO_LEFT_PADDING + MainEditor.LOGO_SIZE * logoSizeTimes,
663      y + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE - MainEditor.NODE_TEXT_SIZE / CONSTANT_MIDDLE, 1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
664    }
665    return w;
666  }
667
668  drawBrokenLine(pm2f, data, offy, i) {
669    let dis =
670      data.parent_ !== undefined ? MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_ : 0;
671    let baseX_ =
672      data.posX +
673      MainEditor.NODE_RECT_WIDTH -
674      (MainEditor.NODE_RECT_WIDTH - data.nodeWidth_) +
675      MainEditor.NODE_TEXT_OFFX +
676      MainEditor.NODE_MORE_CHILD -
677      dis;
678    pm2f.drawLine(
679      baseX_,
680      offy + data.posY + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE,
681      baseX_ + MainEditor.LINE_WIDTH,
682      offy + data.posY + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE,
683      MainEditor.NODE_LINE_COLOR,
684      0.5
685    );
686
687    pm2f.drawLine(
688      baseX_ + MainEditor.LINE_WIDTH,
689      offy + data.posY + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE,
690      baseX_ + MainEditor.LINE_WIDTH,
691      offy + data.value_[i].posY + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE,
692      MainEditor.NODE_LINE_COLOR,
693      0.5
694    );
695
696    pm2f.drawLine(
697      baseX_ + MainEditor.LINE_WIDTH,
698      offy + data.value_[i].posY + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE,
699      baseX_ + MainEditor.LINE_WIDTH * 2,
700      offy + data.value_[i].posY + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE,
701      MainEditor.NODE_LINE_COLOR,
702      0.5
703    );
704  }
705
706  arrayNodeProc(w, pm2f, data, offx, offy) {
707    let ss = '[' + data.value_.length + ']' + NodeTools.arrayToString(data);
708    let keyAndValue = data.parent_.name_ + ' = ';
709
710    if (keyAndValue.length >= KEY_VALUE_MAX) {
711      return;
712    } else if (keyAndValue.length === ONE_KEY_VALUE_MAX) {
713      w = pm2f.drawText('.', MainEditor.NODE_TEXT_SIZE, offx, offy + data.posY + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE -
714      MainEditor.NODE_TEXT_SIZE / CONSTANT_MIDDLE, 1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
715    } else if (keyAndValue.length === TWO_KEY_VALUE_MAX) {
716      w = pm2f.drawText('..', MainEditor.NODE_TEXT_SIZE, offx, offy + data.posY + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE -
717      MainEditor.NODE_TEXT_SIZE / CONSTANT_MIDDLE, 1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
718    } else if (keyAndValue.length === THREE_KEY_VALUE_MAX) {
719      w = pm2f.drawText('...', MainEditor.NODE_TEXT_SIZE, offx, offy + data.posY + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE -
720      MainEditor.NODE_TEXT_SIZE / CONSTANT_MIDDLE, 1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
721    } else if (keyAndValue.length < THREE_KEY_VALUE_MAX) {
722      let displayValueLen = DISPLAY_TEXT_MAX - keyAndValue.length;
723      if (ss.length > displayValueLen) {
724        ss = ss.substring(0, displayValueLen - 3) + '...';
725      }
726      w = pm2f.drawText(ss, MainEditor.NODE_TEXT_SIZE, offx, offy + data.posY + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE -
727      MainEditor.NODE_TEXT_SIZE / CONSTANT_MIDDLE, 1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
728    }
729  }
730
731  configNodeProc(w, pm2f, data, offx, offy, path) {
732    let dis = data.parent_ !== undefined ? MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_ : 0;
733    this.setNodeButton(pm2f, offx, offy + data.posY, w, MainEditor.NODE_TEXT_SIZE, path, data);
734    if (data.value_.length > 0) {
735      this.setNodeMoreButton(pm2f, offx - dis, offy + data.posY, MainEditor.NODE_MORE_CHILD, MainEditor.NODE_MORE_CHILD, data);
736    }
737    let drawNodeX_ = offx + MainEditor.NODE_RECT_WIDTH + MainEditor.NODE_SIZE_BG_OFFX + MainEditor.NODE_MORE_CHILD + MainEditor.LINE_WIDTH * 2 - dis;
738    if (data.type_ === DataType.NODE) {
739      data.value_.forEach((item, index) => {
740        if (item.parent_.type_ === DataType.NODE && item.parent_.isOpen_) {
741          this.drawObj(pm2f, item, drawNodeX_, offy, path + '.');
742          this.drawBrokenLine(pm2f, data, offy, index);
743        } else if (item.parent_.type_ === DataType.ATTR) {
744          this.drawObj(pm2f, item, drawNodeX_, offy, path + '.');
745          pm2f.drawLine(data.posX + w, offy + data.posY + 10,
746            item.posX, offy + item.posY + 10, MainEditor.NODE_TEXT_COLOR, 1);
747        } else {
748          NapiLog.logInfo('Node collapse does not need to draw child node');
749        }
750      });
751    } else {
752      data.value_.forEach((item, index) => {
753        this.drawObj(pm2f, item, drawNodeX_, offy, path + '.');
754        pm2f.drawLine(data.posX + w, offy + data.posY + 10,
755          item.posX, offy + item.posY + 10, MainEditor.NODE_TEXT_COLOR, 1);
756      });
757    }
758  }
759
760  /**
761   * 绘制Attr对象
762   * @param {} pm2f X2DFast
763   * @param {} data 节点数据对象
764   * @param {} offx x偏移值
765   * @param {} offy y偏移值
766   * @param {} path 节点路径
767   */
768  drawAttrObj(pm2f, data, offx, offy, path) {
769    let w = this.drawNode(pm2f, data.name_, MainEditor.NODE_TEXT_SIZE, offx, offy + data.posY, data.type_, data);
770    this.setNodeButton(pm2f, offx, offy + data.posY, w, MainEditor.NODE_TEXT_SIZE, path, data);
771    this.drawObj(pm2f, data.value_, offx + w, offy, path);
772    pm2f.drawCut(this.attrIconCut_, offx + MainEditor.LOGO_LEFT_PADDING - (MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_),
773      offy + data.posY + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE - MainEditor.LOGO_SIZE / CONSTANT_MIDDLE);
774  }
775
776  /**
777   * 绘制Node对象
778   * @param {} pm2f X2DFast
779   * @param {} data 节点数据对象
780   * @param {} offx x偏移值
781   * @param {} offy y偏移值
782   * @param {} path 节点路径
783   */
784  drawNodeObj(pm2f, data, offx, offy, path) {
785    let w = this.drawNode(pm2f, this.getNodeText(data), MainEditor.NODE_TEXT_SIZE, offx, offy + data.posY, data.type_, data);
786    this.configNodeProc(w, pm2f, data, offx, offy, path);
787    if (data.parent_ !== undefined) {
788      pm2f.drawCut(this.nodeIconCut_, offx + MainEditor.LOGO_LEFT_PADDING - (MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_),
789        offy + data.posY + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE - MainEditor.LOGO_SIZE / CONSTANT_MIDDLE);
790    }
791  }
792
793  /**
794   * 绘制引用对象
795   * @param {} pm2f X2DFast
796   * @param {} data 节点数据对象
797   * @param {} drawTextX_ x偏移值
798   * @param {} drawTextY_ y偏移值
799   */
800  drawReferenceObj(pm2f, data, drawTextX_, drawTextY_) {
801    let content = data.parent_.name_ + ' = ';
802    if (content.length > DISPLAY_TEXT_MAX) {
803      content = '';
804    } else if ((content + data.value_).length > DISPLAY_TEXT_MAX) {
805      content = data.value_.substring((data.parent_.name_ + ' = ').length, THREE_KEY_VALUE_MAX) + '...';
806    } else {
807      content = data.value_;
808    }
809    pm2f.drawText('&' + content, MainEditor.NODE_TEXT_SIZE, drawTextX_ - (MainEditor.NODE_RECT_WIDTH - data.parent_.parent_.nodeWidth_), drawTextY_,
810      1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
811  }
812
813  /**
814   * 绘制引用对象
815   * @param {} pm2f X2DFast
816   * @param {} data 节点数据对象
817   * @param {} drawTextX_ x偏移值
818   * @param {} drawTextY_ y偏移值
819   */
820  drawStringObj(pm2f, data, drawTextX_, drawTextY_) {
821    let value = data.value_;
822    let keyAndValue = data.parent_.name_ + ' = ' + data.value_;
823    if (keyAndValue.length > DISPLAY_TEXT_MAX) {
824      value = keyAndValue.substring((data.parent_.name_ + ' = ').length, THREE_KEY_VALUE_MAX) + '...';
825    }
826    let w = pm2f.drawText('"' + value + '"', MainEditor.NODE_TEXT_SIZE, drawTextX_ - (MainEditor.NODE_RECT_WIDTH - data.parent_.parent_.nodeWidth_), drawTextY_,
827      1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
828  }
829
830  drawObj(pm2f, data, offx, offy, path) {
831    let w;
832    path += data.name_;
833    data.posX = offx;
834    if (this.maxX < offx) {
835      this.maxX = offx;
836    }
837    let parentTextWidth = pm2f.getTextWidth(' = ', MainEditor.NODE_TEXT_SIZE);
838    let drawTextX_ = offx + MainEditor.LOGO_LEFT_PADDING + MainEditor.LOGO_SIZE + parentTextWidth;
839    let drawTextY_ = offy + data.posY + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE -
840    MainEditor.NODE_TEXT_SIZE / CONSTANT_MIDDLE;
841    switch (data.type_) {
842      case DataType.INT8:
843      case DataType.INT16:
844      case DataType.INT32:
845      case DataType.INT64:
846        w = pm2f.drawText(NodeTools.jinZhi10ToX(data.value_, data.jinzhi_), MainEditor.NODE_TEXT_SIZE,
847          drawTextX_ - (MainEditor.NODE_RECT_WIDTH - data.parent_.parent_.nodeWidth_),
848          drawTextY_, 1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
849        break;
850      case DataType.STRING:
851        this.drawStringObj(pm2f, data, drawTextX_, drawTextY_);
852        break;
853      case DataType.NODE:
854        this.drawNodeObj(pm2f, data, offx, offy, path);
855        break;
856      case DataType.ATTR:
857        this.drawAttrObj(pm2f, data, offx, offy, path);
858        break;
859      case 8:
860        this.arrayNodeProc(w, pm2f, data, drawTextX_ - (MainEditor.NODE_RECT_WIDTH - data.parent_.parent_.nodeWidth_), offy);
861        break;
862      case DataType.REFERENCE:
863        this.drawReferenceObj(pm2f, data, drawTextX_, drawTextY_);
864        break;
865      case DataType.DELETE:
866        w = pm2f.drawText('delete', MainEditor.NODE_TEXT_SIZE, drawTextX_ - (MainEditor.NODE_RECT_WIDTH - data.parent_.parent_.nodeWidth_), drawTextY_,
867          1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
868        break;
869      case DataType.BOOL:
870        this.drawBoolObj(pm2f, data, drawTextX_, drawTextY_);
871        break;
872      default:
873        NapiLog.logError('unknow' + data.type_);
874        break;
875    }
876    this.drawErrorRect(pm2f, data, offx, offy);
877  }
878
879  /**
880   * 绘制Bool对象
881   * @param {} pm2f X2DFast
882   * @param {} data 节点数据对象
883   * @param {} drawTextX_ x偏移值
884   * @param {} drawTextY_ y偏移值
885   */
886  drawBoolObj(pm2f, data, drawTextX_, drawTextY_) {
887    let w;
888    if (data.value_) {
889      w = pm2f.drawText('true', MainEditor.NODE_TEXT_SIZE, drawTextX_ - (MainEditor.NODE_RECT_WIDTH - data.parent_.parent_.nodeWidth_), drawTextY_,
890        1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
891    } else {
892      w = pm2f.drawText('false', MainEditor.NODE_TEXT_SIZE, drawTextX_ - (MainEditor.NODE_RECT_WIDTH - data.parent_.parent_.nodeWidth_), drawTextY_,
893        1, 1, 0, 1, 1, MainEditor.NODE_TEXT_COLOR);
894    }
895  }
896
897  /**
898   * 绘制错误显示框
899   * @param {} pm2f X2DFast
900   * @param {} data 节点数据对象
901   * @param {} offx x偏移值
902   * @param {} offy y偏移值
903   */
904  drawErrorRect(pm2f, data, offx, offy) {
905    if (data.errMsg_ !== null && data.errMsg_ !== undefined) {
906      let displayFreq = 2; // 显示频率
907      let frameNo = 10;
908      if (parseInt(this.delay_ / frameNo) % displayFreq === 0) {
909        pm2f.drawRect(offx - (MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_), offy + data.posY,
910          data.nodeWidth_, MainEditor.NODE_RECT_HEIGHT, 0xffff0000, 1);
911      }
912      pm2f.drawText(data.errMsg_, MainEditor.NODE_TEXT_SIZE, offx - (MainEditor.NODE_RECT_WIDTH - data.parent_.nodeWidth_),
913        offy + data.posY + 5, 1, 1, 0, -1, -3, 0xffff0000);
914    }
915  }
916
917  /**
918   * 获取绘制框宽度
919   * @param {} pm2f X2DFast
920   * @param {} node 节点数据对象
921   * @return {} rectWidth 绘制框宽度
922   */
923  getRectWidth(pm2f, node) {
924    let displayValue;
925    let rectWidth = 0;
926    if (node.value_.type_ === ObjectType.PARSEROP_ARRAY) {
927      let arrayValue = NodeTools.arrayToString(node.value_);
928      displayValue = '[' + node.value_.value_.length + ']' + arrayValue;
929    } else if (
930      node.value_.type_ === ObjectType.PARSEROP_UINT8 ||
931      node.value_.type_ === ObjectType.PARSEROP_UINT16 ||
932      node.value_.type_ === ObjectType.PARSEROP_UINT32 ||
933      node.value_.type_ === ObjectType.PARSEROP_UINT64
934    ) {
935      displayValue = NodeTools.jinZhi10ToX(
936        node.value_.value_,
937        node.value_.jinzhi_
938      );
939    } else if (node.value_.type_ === ObjectType.PARSEROP_DELETE) {
940      displayValue = 'delete';
941    } else if (node.value_.type_ === ObjectType.PARSEROP_BOOL) {
942      if (node.value_) {
943        displayValue = 'true';
944      } else {
945        displayValue = 'false';
946      }
947    } else {
948      displayValue = node.value_.value_;
949    }
950
951    let keyAndValue;
952    let lenDisplay = THREE_KEY_VALUE_MAX;
953    let moreLenDisplayOne = 1;
954    let moreLenDisplayTwo = 2;
955    if (node.name_.length <= lenDisplay) {
956      keyAndValue = node.name_ + ' = ' + displayValue;
957    } else if (node.name_.length === lenDisplay + moreLenDisplayOne) {
958      keyAndValue = node.name_ + ' =';
959    } else if (node.name_.length === lenDisplay + moreLenDisplayTwo) {
960      keyAndValue = node.name_ + '=';
961    } else if (node.name_.length >= DISPLAY_TEXT_MAX) {
962      keyAndValue = node.name_;
963    }
964
965    if (keyAndValue.length >= DISPLAY_TEXT_MAX) {
966      keyAndValue = keyAndValue.substring(0, THREE_KEY_VALUE_MAX) + '...';
967    }
968    rectWidth = pm2f.getTextWidth(keyAndValue, MainEditor.NODE_TEXT_SIZE);
969    return rectWidth;
970  }
971
972  /**
973   * 绘制节点名称
974   * @param {} pm2f X2DFast
975   * @param {} node 节点数据对象
976   * @param {} x x坐标值
977   * @param {} y y坐标值
978   * @param {} w 宽度
979   * @param {} h 高度
980   */
981  drawNodeNameText(pm2f, node, x, y, w, h) {
982    pm2f.drawText(
983      node.name_,
984      MainEditor.NODE_TEXT_SIZE,
985      x + MainEditor.NODE_RECT_WIDTH / CONSTANT_MIDDLE - w / CONSTANT_MIDDLE,
986      y + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE - h / CONSTANT_MIDDLE,
987      1,
988      1,
989      0,
990      1,
991      1,
992      MainEditor.NODE_TEXT_COLOR
993    );
994  }
995
996  setNodeButton(pm2f, x, y, w, h, path, node) {
997    let rectWidth = MainEditor.NODE_RECT_WIDTH;
998    if (node.parent_ === undefined) {
999      if (this.nodePoint_ === node) {
1000        pm2f.drawCut(this.rootIconFocusCut_, x, y);
1001      } else {
1002        pm2f.drawCut(this.rootIconCut_, x, y);
1003      }
1004      node.nodeWidth_ = MainEditor.NODE_RECT_WIDTH;
1005      this.drawNodeNameText(pm2f, node, x, y, w, h);
1006    } else {
1007      if (node.type_ === DataType.ATTR) {
1008        rectWidth = this.getRectWidth(pm2f, node);
1009      } else {
1010        rectWidth = pm2f.getTextWidth(
1011          this.getNodeText(node).length > DISPLAY_TEXT_MAX ? this.getNodeText(node).substring(0, THREE_KEY_VALUE_MAX) + '...' : this.getNodeText(node),
1012          MainEditor.NODE_TEXT_SIZE
1013        );
1014      }
1015      this.drawNodeRectButton(pm2f, x, y, rectWidth, node);
1016    }
1017
1018    if (this.nodeBtnPoint_ >= this.nodeBtns.length) {
1019      this.nodeBtns.push(new XButton());
1020    }
1021    let pbtn = this.nodeBtns[this.nodeBtnPoint_];
1022    let singleOffset = 6;
1023    let numberOffset = 2;
1024    let widthOffset = singleOffset * numberOffset;
1025    let logoSizeOffset = 8;
1026    pbtn.move(
1027      x - (node.parent_ === undefined ? 0 : MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_),
1028      y, node.parent_ === undefined ? MainEditor.NODE_RECT_WIDTH : rectWidth + widthOffset + MainEditor.LOGO_SIZE + logoSizeOffset, MainEditor.NODE_RECT_HEIGHT
1029    );
1030    pbtn.name_ = path;
1031    pbtn.node_ = node;
1032    this.nodeBtnPoint_ += 1;
1033  }
1034
1035  drawNodeRectButton(pm2f, x, y, rectWidth, node) {
1036    let singleOffset = 6;
1037    let numberOffset = 2;
1038    let widthOffset = singleOffset * numberOffset;
1039    let logoSizeOffset = 8;
1040    let width = rectWidth + widthOffset + MainEditor.LOGO_SIZE + logoSizeOffset;
1041    if (node.type_ === DataType.ATTR) {
1042      switch (node.value_.type_) {
1043        case ObjectType.PARSEROP_UINT8:
1044        case ObjectType.PARSEROP_UINT16:
1045        case ObjectType.PARSEROP_UINT32:
1046        case ObjectType.PARSEROP_UINT64:
1047        case ObjectType.PARSEROP_ARRAY:
1048          width = width;
1049          break;
1050        default:
1051          width = width + 14;
1052          break;
1053      }
1054    }
1055    if (this.nodePoint_ === node) {
1056      if (this.isSearchResult_) {
1057        pm2f.drawCut(this.leftSearchAttrCicleCut_, x - (MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_), y);
1058        pm2f.drawCut(this.centerSearchAttrCut_, x + 8 - (MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_), y, width / 116);
1059        pm2f.drawCut(this.rightSearchAttrCicleCut_, x + 8 + width - (MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_), y);
1060      } else {
1061        pm2f.drawCut(this.leftRectFocusCicleCut_, x - (MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_), y);
1062        pm2f.drawCut(this.centerFocusCut_, x + 8 - (MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_), y, width / 116);
1063        pm2f.drawCut(this.rightRectFocusCicleCut_, x + 8 + width - (MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_), y);
1064      }
1065    } else {
1066      if (this.searchKey !== null && node.name_.indexOf(this.searchKey) > -1 && this.isSearchResult_) {
1067        pm2f.drawCut( this.leftSearchFocusCicleCut_, x - (MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_), y);
1068        pm2f.drawCut(this.centerSearchCut_, x + 8 - (MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_), y, width / 116);
1069        pm2f.drawCut( this.rightSearchFocusCicleCut_, x + 8 + width - (MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_), y);
1070      } else {
1071        pm2f.drawCut( this.leftRectCicleCut_, x - (MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_), y);
1072        pm2f.drawCut( this.centerRectCut_, x + 8 - (MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_), y, width / 116);
1073        pm2f.drawCut(this.rightRectCicleCut_, x + 8 + width - (MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_), y);
1074      }
1075    }
1076    node.nodeWidth_ = 8 * 2 + width;
1077    let tx = x + 8 + width - (MainEditor.NODE_RECT_WIDTH - node.parent_.nodeWidth_) + 8;
1078    if (this.maxX < tx) {
1079      this.maxX = tx;
1080    }
1081  }
1082
1083  /**
1084   * 绘制节点数
1085   * @param {} pm2f X2DFast
1086   * @param {*} x 起始x坐标
1087   * @param {*} y 起始y坐标
1088   * @param {*} h 节点高度
1089   * @param {*} node 节点
1090   */
1091  setNodeMoreButton(pm2f, x, y, w, h, node) {
1092    if (this.nodeMoreBtnPoint_ >= this.nodeMoreBtns.length) {
1093      this.nodeMoreBtns.push(new XButton());
1094    }
1095    let pbtn = this.nodeMoreBtns[this.nodeMoreBtnPoint_];
1096    if (node.parent_ === undefined) {
1097      pbtn.move(x + MainEditor.NODE_RECT_WIDTH + MainEditor.NODE_SIZE_BG_OFFX,
1098        y + (MainEditor.NODE_RECT_HEIGHT - MainEditor.NODE_MORE_CHILD) / CONSTANT_MIDDLE, w, h);
1099    } else {
1100      if (node.isOpen_) {
1101        pbtn.move(x + node.nodeWidth_ + MainEditor.NODE_SIZE_BG_OFFX,
1102          y + (MainEditor.NODE_RECT_HEIGHT - MainEditor.NODE_MORE_CHILD) / CONSTANT_MIDDLE, w, h);
1103      } else {
1104        pbtn.move(x + node.nodeWidth_ + MainEditor.NODE_SIZE_BG_OFFX,
1105          y + (MainEditor.NODE_RECT_HEIGHT - MainEditor.NODE_MORE_CHILD) / CONSTANT_MIDDLE, w, h);
1106      }
1107    }
1108    if (node.isOpen_) {
1109      pm2f.drawCut(this.circleOpenCut_, x + node.nodeWidth_ + MainEditor.NODE_SIZE_BG_OFFX,
1110        y + (MainEditor.NODE_RECT_HEIGHT - MainEditor.NODE_MORE_CHILD) / CONSTANT_MIDDLE);
1111    } else {
1112      let c = 0xffffffff;
1113      let oy = 1;
1114      let ox = 1;
1115      let ra = 0;
1116      let sh = 1;
1117      let sw = 1;
1118      let yOffset = 4;
1119      let textSize = 10;
1120      pm2f.drawCut(this.circleCut_, x + node.nodeWidth_ + MainEditor.NODE_SIZE_BG_OFFX,
1121        y + (MainEditor.NODE_RECT_HEIGHT - MainEditor.NODE_MORE_CHILD) / CONSTANT_MIDDLE);
1122      let textWidth = pm2f.getTextWidth(node.value_.length, 10);
1123      pm2f.drawText(node.value_.length, textSize, x + node.nodeWidth_ + MainEditor.NODE_SIZE_BG_OFFX +
1124        MainEditor.NODE_MORE_CHILD / CONSTANT_MIDDLE - textWidth / CONSTANT_MIDDLE,
1125        y + MainEditor.NODE_RECT_HEIGHT / CONSTANT_MIDDLE - yOffset, sw, sh, ra, ox, oy, c);
1126    }
1127    pbtn.node_ = node;
1128    this.nodeMoreBtnPoint_ += 1;
1129  }
1130
1131  /**
1132   * 移动绘制
1133   * @param {} xOffset x偏移值
1134   */
1135  moveAndDraw(xOffset) {
1136    let x = 16;
1137    let y = 20;
1138    let w = window.innerWidth - xOffset - DRAW_HEIGHT - x;
1139    let h = 20;
1140    this.sltInclude.move(x, y, w, h).draw();
1141  }
1142
1143  /**
1144   * 绘制Rect
1145   * @param {} pm2f X2DFast
1146   * @param {*} xx 起始x坐标
1147   * @param {*} yy 起始y坐标
1148   * @param {*} xOffset x偏移值
1149   */
1150  fillWholeRect(pm2f, xx, yy, xOffset) {
1151    pm2f.fillRect(xx, yy, window.innerWidth, DRAW_HEIGHT, MainEditor.CANVAS_LINE);
1152    pm2f.fillRect(
1153      window.innerWidth - xOffset - DRAW_HEIGHT,
1154      0,
1155      DRAW_HEIGHT,
1156      window.innerHeight,
1157      MainEditor.CANVAS_LINE
1158    );
1159    yy = 4;
1160    let wSpace = 4;
1161    let h = 48;
1162    pm2f.fillRect(xx, yy, window.innerWidth - xOffset - wSpace, h, MainEditor.CANVAS_BG);
1163    yy = 52;
1164    pm2f.fillRect(
1165      xx,
1166      yy,
1167      window.innerWidth - xOffset - DRAW_HEIGHT,
1168      DRAW_HEIGHT,
1169      MainEditor.CANVAS_LINE
1170    );
1171  }
1172
1173  /**
1174   * 修改节点位置
1175   */
1176  subFuncModify() {
1177    this.offX_ -= this.modifyPos_.node.posX - this.modifyPos_.x;
1178    this.offY_ -= this.modifyPos_.node.posY - this.modifyPos_.y;
1179    this.modifyPos_ = null;
1180  }
1181
1182  /**
1183   * 绘制Rect
1184   * @param {} pm2f X2DFast
1185   * @param {*} x 起始x坐标
1186   * @param {*} y 起始y坐标
1187   * @param {*} data 绘制的数据对象
1188   */
1189  subFuncFirstDraw(pm2f, x, y, data) {
1190    this.offX_ = 0;
1191    this.offY_ = -data.posY + Scr.logich / CONSTANT_MIDDLE;
1192    this.maxX = 0;
1193    this.drawObj(pm2f, data, this.offX_, this.offY_, '');
1194    pm2f.fillRect(x, y, Scr.logicw, Scr.logich, MainEditor.CANVAS_BG);
1195    this.offX_ = (Scr.logicw - this.maxX) / CONSTANT_MIDDLE;
1196    this.isFirstDraw = false;
1197  }
1198
1199  /**
1200   * 绘制接口
1201   * @param {} pm2f X2DFast
1202   * @param {*} xx 起始x坐标
1203   * @param {*} yy 起始y坐标
1204   */
1205  subFuncDraw(pm2f, xx, yy) {
1206    let data = this.files_[this.filePoint_];
1207    this.calcPostionY(data, 0);
1208    if (this.modifyPos_) {
1209      this.subFuncModify();
1210    } else if (this.isFirstDraw) {
1211      this.subFuncFirstDraw(pm2f, xx, yy, data);
1212    }
1213    this.nodeBtnPoint_ = 0;
1214    this.nodeMoreBtnPoint_ = 0;
1215    this.drawObj(pm2f, data, this.offX_, this.offY_, '');
1216  }
1217
1218  /**
1219   * 绘制选择文本
1220   * @param {} pm2f X2DFast
1221   */
1222  drawSelectText(pm2f) {
1223    let drawTextName = '点击选择目标';
1224    this.callDrawText(pm2f, drawTextName);
1225    this.btnCancelSelect_.name_ = '取消选择';
1226  }
1227
1228  callDrawText(pm2f, drawTextName) {
1229    pm2f.drawText(drawTextName, MainEditor.NODE_TEXT_SIZE, this.mousePos_.x,
1230      this.mousePos_.y, 1, 1, 0, DRAWTEXT_OFFSETX, DRAWTEXT_OFFSETY, MainEditor.NODE_TEXT_COLOR);
1231  }
1232
1233  /**
1234   * 绘制复制文本
1235   * @param {} pm2f X2DFast
1236   */
1237  drawCopyText(pm2f) {
1238    let drawTextName = '已复制' + this.selectNode_.pnode.name_;
1239    this.callDrawText(pm2f, drawTextName);
1240    this.btnCancelSelect_.name_ = '取消复制';
1241  }
1242
1243  /**
1244   * 绘制剪切文本
1245   * @param {} pm2f X2DFast
1246   * @param {*} xx 起始x坐标
1247   * @param {*} yy 起始y坐标
1248   */
1249  drawCutText(pm2f) {
1250    pm2f.drawText(
1251      '已剪切' + this.selectNode_.pnode.name_,
1252      18,
1253      this.mousePos_.x,
1254      this.mousePos_.y,
1255      1,
1256      1,
1257      0,
1258      -3,
1259      -3,
1260      MainEditor.NODE_TEXT_COLOR
1261    );
1262    this.btnCancelSelect_.name_ = '取消剪切';
1263  }
1264
1265  /**
1266   * 绘制错误信息文本
1267   * @param {} pm2f X2DFast
1268   * @param {*} xx 起始x坐标
1269   * @param {*} yy 起始y坐标
1270   */
1271  drawErrorText(pm2f, a, y) {
1272    a = a << 24;
1273    pm2f.fillRect(0, y, Scr.logicw, 20, 0xff0000 | a);
1274    pm2f.drawText(
1275      this.errorMsg_[i][1],
1276      MainEditor.NODE_TEXT_SIZE,
1277      Scr.logicw / CONSTANT_MIDDLE,
1278      y,
1279      1,
1280      1,
1281      0,
1282      -2,
1283      -1,
1284      MainEditor.NODE_TEXT_COLOR
1285    );
1286  }
1287
1288  /**
1289   * 绘制一组剪切文本
1290   * @param {} pm2f X2DFast
1291   * @param {*} xx 起始x坐标
1292   * @param {*} yy 起始y坐标
1293   */
1294  drawCuts(pm2f, x, y) {
1295    let xOffset = 28;
1296    let yDoubleOffset = 56;
1297    let ySpace = 8;
1298    pm2f.drawCut(this.searchBgCut_, x, y);
1299    pm2f.drawCut(this.searchCut_, x + xOffset, y + yDoubleOffset / CONSTANT_MIDDLE - ySpace);
1300    x = x + 16 + 290 + 16;
1301
1302    let searchResultTxt =
1303    this.searchInput.result.length === 0 ? 'No result' : this.searchInput.point + 1 + '/' + this.searchInput.result.length;
1304    let color = 0xffffffff;
1305    let offsetY = -2;
1306    let offsetX = -1;
1307    let ra = 0;
1308    let sh = 1;
1309    let sw = 1;
1310    let yOffsetBase = 56;
1311    let yOffset = 3;
1312    let xStep = 16;
1313    let yRightSpace = 8;
1314    let start = 74;
1315
1316    x += pm2f.drawText(
1317      searchResultTxt,
1318      MainEditor.NODE_TEXT_SIZE,
1319      x,
1320      y + yOffsetBase / CONSTANT_MIDDLE + yOffset,
1321      sw,
1322      sh,
1323      ra,
1324      offsetX,
1325      offsetY,
1326      color
1327    );
1328    x += start - pm2f.getTextWidth(searchResultTxt, MainEditor.NODE_TEXT_SIZE);
1329    pm2f.drawCut(this.upCut_, x, y + yOffsetBase / CONSTANT_MIDDLE - yRightSpace);
1330    this.searchInput.btnUp.move(x, y + yOffsetBase / CONSTANT_MIDDLE - yRightSpace, xStep, xStep);
1331    x += xStep + xStep;
1332    pm2f.drawCut(this.downCut_, x, y + yOffsetBase / CONSTANT_MIDDLE - yRightSpace);
1333    this.searchInput.btnDown.move(x, y + yOffsetBase / CONSTANT_MIDDLE - yRightSpace, xStep, xStep);
1334    x += xStep + xStep;
1335    pm2f.drawCut(this.closeCut_, x, y + yOffsetBase / CONSTANT_MIDDLE - yRightSpace);
1336    this.searchInput.btnClose.move(x, y + yOffsetBase / CONSTANT_MIDDLE - yRightSpace, xStep, xStep);
1337  }
1338
1339  /**
1340   * MainEditor绘制
1341   * @param {} pm2f X2DFast
1342   */
1343  draw(pm2f) {
1344    let xx = 0;
1345    let yy = 0;
1346    getVsCodeTheme();
1347    pm2f.fillRect(xx, yy, Scr.logicw, Scr.logich, MainEditor.CANVAS_BG);
1348    if (this.filePoint_ !== null && this.filePoint_ in this.files_) {
1349      this.subFuncDraw(pm2f, xx, yy);
1350    }
1351    let xOffset = 420;
1352    this.fillWholeRect(pm2f, xx, yy, xOffset);
1353    this.sltInclude.setColor(MainEditor.CANVAS_BG, MainEditor.NODE_TEXT_COLOR);
1354    this.moveAndDraw(xOffset);
1355
1356    if (this.selectNode_.type !== null) {
1357      if (this.selectNode_.type === 'change_target') {
1358        this.drawSelectText(pm2f);
1359      } else if (this.selectNode_.type === 'copy_node') {
1360        this.drawCopyText(pm2f);
1361      } else if (this.selectNode_.type === 'cut_node') {
1362        this.drawCutText(pm2f);
1363      }
1364      this.btnCancelSelect_.move(Scr.logicw - 250, Scr.logich - 30, 100, 20);
1365    }
1366
1367    if (this.errorMsg_.length > 0) {
1368      let ts = new Date().getTime();
1369      while (this.errorMsg_.length > 0 && this.errorMsg_[0][0] < ts) {
1370        this.errorMsg_.shift();
1371      }
1372
1373      this.errorMsg_.forEach((item, index) => {
1374        let sizeNumber = 20;
1375        let y = Scr.logich / CONSTANT_MIDDLE - this.errorMsg_.length * sizeNumber + i * sizeNumber;
1376        let a = parseInt((item[0] - ts) / CONSTANT_MIDDLE);
1377        if (a > MAX_RANDOM) {
1378          a = MAX_RANDOM;
1379        }
1380        NapiLog.logError(a);
1381        this.drawErrorText(pm2f, a, y);
1382      });
1383    }
1384
1385    this.delay_ += 1;
1386    RightMenu.Draw();
1387    if (this.searchInput) {
1388      let x = this.searchInput.pos[0];
1389      let y = this.searchInput.pos[1];
1390      this.drawCuts(pm2f, x, y);
1391    }
1392    this.procAll();
1393  }
1394
1395  buttonClickedProc(nodeBtns) {
1396    if (
1397      this.selectNode_.type === null || this.selectNode_.type === 'copy_node' ||
1398      this.selectNode_.type === 'cut_node') {
1399      this.nodePoint_ = nodeBtns.node_;
1400      AttrEditor.gi().freshEditor(this.filePoint_, this.nodePoint_);
1401      return true;
1402    }
1403    if (this.selectNode_.type === 'change_target') {
1404      let pn = nodeBtns.node_;
1405      if (pn.type_ === DataType.NODE) {
1406        if (this.selectNode_.pnode.type_ === DataType.NODE) {
1407          if (
1408            NodeTools.getPathByNode(this.selectNode_.pnode.parent_) ===
1409            NodeTools.getPathByNode(pn.parent_)
1410          ) {
1411            this.selectNode_.pnode.ref_ = pn.name_;
1412          } else {
1413            this.selectNode_.pnode.ref_ = NodeTools.getPathByNode(pn);
1414          }
1415        } else if (this.selectNode_.pnode.type_ === DataType.REFERENCE) {
1416          if (
1417            NodeTools.getPathByNode(this.selectNode_.pnode.parent_.parent_) ===
1418            NodeTools.getPathByNode(pn.parent_)
1419          ) {
1420            this.selectNode_.pnode.value_ = pn.name_;
1421          } else {
1422            this.selectNode_.pnode.value_ = NodeTools.getPathByNode(pn);
1423          }
1424        }
1425
1426        this.selectNode_.type = null;
1427        AttrEditor.gi().freshEditor(this.filePoint_, this.nodePoint_);
1428        this.onAttributeChange('writefile');
1429      } else {
1430        XMessage.gi().send('WrongNode', '');
1431      }
1432    }
1433    return true;
1434  }
1435
1436  dropAllLocked(msg, x, y) {
1437    if (msg === MouseType.MOVE) {
1438      this.offX_ += x - this.dropAll_.oldx;
1439      this.offY_ += y - this.dropAll_.oldy;
1440      this.dropAll_.oldx = x;
1441      this.dropAll_.oldy = y;
1442    }
1443    if (msg === MouseType.UP) {
1444      this.dropAll_.locked = false;
1445    }
1446  }
1447
1448  procTouch(msg, x, y) {
1449    const ADD = 6;
1450    const DELETE = 7;
1451    if (this.searchInput) {
1452      if (XTools.InRect(x, y, ...this.searchInput.pos)) {
1453        if (this.searchInput.btnUp.procTouch(msg, x, y)) {
1454          if (this.searchInput.btnUp.isClicked()) {
1455            this.searchInput.point -= 1;
1456            if (this.searchInput.point < 0) {
1457              this.searchInput.point = this.searchInput.result.length - 1;
1458            }
1459            this.locateNode(this.searchInput.result[this.searchInput.point]);
1460          }
1461        }
1462        if (this.searchInput.btnDown.procTouch(msg, x, y)) {
1463          if (this.searchInput.btnDown.isClicked()) {
1464            this.searchInput.point += 1;
1465            if (this.searchInput.point >= this.searchInput.result.length) {
1466              this.searchInput.point = 0;
1467            }
1468            this.locateNode(this.searchInput.result[this.searchInput.point]);
1469          }
1470        }
1471        return true;
1472      } else {
1473        if (msg === MouseType.DOWN) {
1474          this.searchInput = null;
1475          this.isSearchResult_ = false;
1476        }
1477        return true;
1478      }
1479    }
1480
1481    if (RightMenu.Touch(msg, x, y)) {
1482      return true;
1483    }
1484    this.mousePos_.x = x;
1485    this.mousePos_.y = y;
1486    if (this.dropAll_.locked) {
1487      this.dropAllLocked(msg, x, y);
1488      return true;
1489    }
1490
1491    if (this.sltInclude.procTouch(msg, x, y)) {
1492      return true;
1493    }
1494
1495    if (this.selectNode_.type !== null) {
1496      if (this.btnCancelSelect_.procTouch(msg, x, y)) {
1497        if (this.btnCancelSelect_.isClicked()) {
1498          this.selectNode_.type = null;
1499        }
1500        return true;
1501      }
1502    }
1503
1504    for (let i = 0; i < this.nodeBtns.length; i++) {
1505      if (this.nodeBtns[i].procTouch(msg, x, y)) {
1506        let nodeBtns = this.nodeBtns[i];
1507        if (nodeBtns.isClicked()) {
1508          this.buttonClickedProc(nodeBtns);
1509        } else if (nodeBtns.isRightClicked()) {
1510          this.onAttributeChange('change_current_select', nodeBtns.node_);
1511          switch (nodeBtns.node_.type_) {
1512            case ADD:
1513              RightMenu.Reset(
1514                [
1515                  RightMenu.Button(null, 'Add Child Node', null, () => {
1516                    this.procAddNodeAction();
1517                    this.onAttributeChange('writefile');
1518                  }),
1519                  RightMenu.Button(null, 'Add Sub Property', null, () => {
1520                    this.procAddAttAction();
1521                    this.onAttributeChange('writefile');
1522                  }),
1523                  RightMenu.Button(null, 'Delete', null, () => {
1524                    this.procDeleteAction();
1525                    this.onAttributeChange('writefile');
1526                  }),
1527                ],
1528                nodeBtns.posX_,
1529                nodeBtns.posY_ + MainEditor.NODE_RECT_HEIGHT
1530              );
1531              break;
1532            case DELETE:
1533              RightMenu.Reset(
1534                [
1535                  RightMenu.Button(null, 'Delete', null, () => {
1536                    this.procDeleteAction();
1537                    this.onAttributeChange('writefile');
1538                  }),
1539                ],
1540                nodeBtns.posX_,
1541                nodeBtns.posY_ + MainEditor.NODE_RECT_HEIGHT
1542              );
1543              break;
1544          }
1545        }
1546
1547        return true;
1548      }
1549  }
1550
1551    this.nodeMoreBtns.forEach((item, index) => {
1552      if (item.procTouch(msg, x, y)) {
1553        let nodeMoreBtn = item;
1554        if (nodeMoreBtn.isClicked()) {
1555          this.buttonClickedProc(nodeMoreBtn);
1556          item.node_.isOpen_ = !item.node_.isOpen_;
1557          this.modifyPos_ = {
1558            node: item.node_,
1559            x: item.node_.posX,
1560            y: item.node_.posY,
1561          };
1562        }
1563        return true;
1564      }
1565    });
1566
1567    if (msg === MouseType.DOWN && !this.dropAll_.locked) {
1568      this.dropAll_.locked = true;
1569      this.dropAll_.oldx = x;
1570      this.dropAll_.oldy = y;
1571      return true;
1572    }
1573    return false;
1574  }
1575
1576  procAddNodeAction() {
1577    let pattr = AttrEditor.gi();
1578    pattr.changeDataNodeNotInherit('add_child_node', 'button', '');
1579  }
1580
1581  procAddAttAction() {
1582    let pattr = AttrEditor.gi();
1583    pattr.changeDataNodeNotInherit('add_child_attr', 'button', '');
1584  }
1585
1586  procDeleteAction() {
1587    let pattr = AttrEditor.gi();
1588    pattr.changeDataNodeNotInherit('delete', 'button', '');
1589  }
1590  searchNodeByName(data, name, out) {
1591    this.searchKey = name;
1592    if (data.name_.indexOf(name) >= 0) {
1593      out.push(data);
1594    }
1595    switch (data.type_) {
1596      case DataType.NODE:
1597        data.value_.forEach((item, index) => {
1598          this.searchNodeByName(item, name, out);
1599        });
1600        break;
1601      case DataType.ATTR:
1602        this.searchNodeByName(data.value_, name, out);
1603        break;
1604    }
1605  }
1606  expandAllParents(curNdoe) {
1607    if (curNdoe.parent_) {
1608      curNdoe.parent_.isOpen_ = true;
1609      this.expandAllParents(curNdoe.parent_);
1610    }
1611  }
1612  locateNode(node) {
1613    if (!node) {
1614      return;
1615    }
1616    this.expandAllParents(node);
1617    this.isSearchResult_ = true;
1618    this.offX_ -= node.posX - Scr.logicw / CONSTANT_MIDDLE;
1619    this.offY_ -= this.offY_ + node.posY - Scr.logich / CONSTANT_MIDDLE;
1620    this.nodePoint_ = node;
1621    AttrEditor.gi().freshEditor();
1622  }
1623
1624  /**
1625   * Ctrl+Z 快捷键处理
1626   */
1627  procCtrlZ() {
1628    let h;
1629    if (this.historyZ.length <= 0) {
1630      h = this.historyBase[this.filePoint_];
1631    } else {
1632      if (this.historyZ.length > 1 && this.historyPushed) {
1633        this.historyZ.pop();
1634        this.historyPushed = false;
1635      }
1636      h = this.historyZ.pop();
1637    }
1638
1639    this.filePoint_ = h.fn;
1640    this.rootPoint_ = h.fn;
1641    Lexer.FILE_AND_DATA[this.filePoint_] = h.data;
1642    this.parse(this.filePoint_);
1643    if (h.sel) {
1644      this.nodePoint_ = NodeTools.getNodeByPath(
1645        this.files_[this.filePoint_],
1646        h.sel
1647      );
1648    } else {
1649      this.nodePoint_ = null;
1650    }
1651    AttrEditor.gi().freshEditor(this.filePoint_, this.nodePoint_);
1652  }
1653
1654  /**
1655   * Ctrl+F 快捷键处理
1656   */
1657  procCtrlF() {
1658    let xOffset = 300;
1659    let posWidth = 450;
1660    let posHeight = 40;
1661    this.searchInput = {
1662      pos: [(Scr.logicw - xOffset) / CONSTANT_MIDDLE, Scr.logich / CONSTANT_QUARTER, posWidth, posHeight],
1663      result: [],
1664      point: 0,
1665      btnUp: new XButton(0, 0, 0, 0, '上一个'),
1666      btnDown: new XButton(0, 0, 0, 0, '下一个'),
1667      btnClose: new XButton(0, 0, 0, 0, '关闭'),
1668    };
1669    let x = this.searchInput.pos[0];
1670    let y = this.searchInput.pos[1];
1671    let w = this.searchInput.pos[2];
1672    let h = this.searchInput.pos[3];
1673    let width = 258;
1674    let height = 32;
1675    let hOffset = 20;
1676    CanvasInput.Reset(x, y + (h - hOffset) / CONSTANT_MIDDLE, width, height, '', null, (v) => {
1677      this.searchInput.result = [];
1678      if (v.length > 0) {
1679        this.searchNodeByName(
1680          this.files_[this.filePoint_],
1681          v,
1682          this.searchInput.result
1683        );
1684        if (this.searchInput.result.length > 0) {
1685          this.locateNode(this.searchInput.result[0]);
1686          this.searchInput.point = 0;
1687        }
1688      }
1689    });
1690    CanvasInput.SetSafeArea(...this.searchInput.pos);
1691  }
1692
1693  /**
1694   * Ctrl+V 快捷键处理
1695   */
1696  procCtrlV() {
1697    if (this.selectNode_.type !== null && this.nodePoint_ !== null) {
1698      let parent = this.nodePoint_;
1699      if (this.nodePoint_.type_ !== DataType.NODE) {
1700        parent = this.nodePoint_.parent_;
1701      }
1702      parent.value_.push(NodeTools.copyNode(this.selectNode_.pnode, parent));
1703      if (this.selectNode_.type === 'cut_node') {
1704        ModifyNode.deleteNode(this.selectNode_.pnode);
1705        this.selectNode_.type = null;
1706      }
1707      this.checkAllError();
1708    }
1709  }
1710
1711  procKey(k) {
1712    if (k === 'ctrl+z') {
1713      if (this.selectNode_.type !== null) {
1714        this.selectNode_.type = null;
1715      }
1716      console.log('!!! popHistory ', this.historyZ.length);
1717      this.procCtrlZ();
1718    } else if (k === 'ctrl+f') {
1719      this.procCtrlF();
1720    } else if (k === 'ctrl+c') {
1721      if (this.nodePoint_ !== null) {
1722        this.selectNode_ = {
1723          type: 'copy_node',
1724          pnode: this.nodePoint_,
1725        };
1726      }
1727    } else if (k === 'ctrl+x') {
1728      if (this.nodePoint_ !== null) {
1729        this.selectNode_ = {
1730          type: 'cut_node',
1731          pnode: this.nodePoint_,
1732        };
1733      }
1734    } else if (k === 'ctrl+v') {
1735      this.procCtrlV();
1736    } else if (k === 'Delete') {
1737      if (this.nodePoint_ !== null) {
1738        ModifyNode.deleteNode(this.nodePoint_);
1739        AttrEditor.gi().freshEditor();
1740      }
1741    }
1742  }
1743
1744  procAll() {
1745    while (this.touchQueue_.length > 0) {
1746      let touch = this.touchQueue_.shift();
1747      let msgIndex = 0;
1748      let xIndex = 1;
1749      let yIndex = 2;
1750      this.procTouch(touch[msgIndex], touch[xIndex], touch[yIndex]);
1751    }
1752
1753    while (this.keyQueue_.length > 0) {
1754      let k = this.keyQueue_.shift();
1755      this.procKey(k);
1756    }
1757  }
1758  onSelectInclude(sel) {
1759    MainEditor.gi().filePoint_ = sel;
1760    MainEditor.gi().rootPoint_ = sel;
1761    AttrEditor.gi().freshEditor();
1762  }
1763
1764  nodeCount(data) {
1765    let ret = 1;
1766    switch (data.type_) {
1767      case 1:
1768      case 2:
1769      case 3:
1770      case 4:
1771      case 5:
1772        break;
1773      case 6:
1774        data.value_.forEach((item, index) => {
1775          ret += this.nodeCount(item);
1776        });
1777        break;
1778      case 7:
1779        ret += this.nodeCount(data.value_);
1780        break;
1781      case 8:
1782      case 9:
1783      case 10:
1784      case 11:
1785        break;
1786      default:
1787        NapiLog.logError('unknow' + data.type_);
1788        break;
1789    }
1790    return ret;
1791  }
1792  isNodeCountChanged(fn, bset = true) {
1793    if (!(fn in this.nodeCount_)) {
1794      this.nodeCount_[fn] = -1;
1795    }
1796    let newcount = this.nodeCount(this.files_[fn]);
1797    if (this.nodeCount_[fn] !== newcount) {
1798      if (bset) {
1799        this.nodeCount_[fn] = newcount;
1800      }
1801      return true;
1802    }
1803    return false;
1804  }
1805  saveHistory(fn, data2, pth, pos = null) {
1806    console.log('!!! save History ', this.historyZ.length, pos);
1807    if (fn in this.historyBase) {
1808      this.historyZ.push({
1809        fn: fn,
1810        data: data2,
1811        sel: pth,
1812      });
1813      this.historyPushed = true;
1814    } else {
1815      this.historyBase[fn] = {
1816        fn: fn,
1817        data: data2,
1818        sel: pth,
1819      };
1820    }
1821  }
1822  onAttributeChange(type, value) {
1823    let pme = MainEditor.gi();
1824    let lenChangeTarget = 13;
1825    if (type === 'writefile') {
1826      let data1 = Generator.gi().makeHcs(pme.filePoint_, pme.files_[pme.filePoint_]);
1827      let data2 = [];
1828      let dataCharArr = Array.from(data1);
1829      dataCharArr.forEach((item, index) => {
1830        data2.push(data1.charCodeAt(index));
1831      });
1832      if (pme.isNodeCountChanged(pme.filePoint_)) {
1833        Lexer.FILE_AND_DATA[pme.filePoint_] = data2;
1834        pme.parse(pme.filePoint_);
1835        let t = NodeTools.getPathByNode(pme.nodePoint_, false);
1836        if (t) {
1837          pme.nodePoint_ = NodeTools.getNodeByPath(pme.files_[pme.filePoint_], t);
1838        } else {
1839          pme.nodePoint_ = null;
1840        }
1841        if (pme.selectNode_.pnode) {
1842          let t = NodeTools.getPathByNode(pme.selectNode_.pnode, false);
1843          if (t) {
1844            pme.selectNode_.pnode = NodeTools.getNodeByPath(pme.files_[pme.filePoint_], t);
1845          } else {
1846            pme.selectNode_.pnode = null;
1847          }
1848        }
1849        AttrEditor.gi().freshEditor(pme.filePoint_, pme.nodePoint_);
1850      }
1851      pme.checkAllError();
1852      XMessage.gi().send('writefile', {
1853        fn: pme.filePoint_,
1854        data: data1,
1855      });
1856      pme.saveHistory(pme.filePoint_, data2, NodeTools.getPathByNode(pme.nodePoint_), 1);
1857    } else if (type.substring(0, lenChangeTarget) === 'change_target') {
1858      pme.selectNode_.type = type;
1859      pme.selectNode_.pnode = value;
1860    } else if (type.startsWith('cancel_change_target')) {
1861      pme.selectNode_.type = null;
1862    } else if (type === 'change_current_select') {
1863      pme.nodePoint_ = value;
1864      AttrEditor.gi().freshEditor(pme.filePoint_, pme.nodePoint_);
1865    }
1866  }
1867  onError(msg) {}
1868  onTouch(msg, x, y) {
1869    this.touchQueue_.push([msg, x, y]);
1870  }
1871  onKey(k) {
1872    this.keyQueue_.push(k);
1873  }
1874  onReceive(type, data) {
1875    console.log('onReceive type=' + type);
1876    NapiLog.logError(type);
1877    let me = MainEditor.gi();
1878    if (type === 'parse') {
1879      me.parse(data);
1880    } else if (type === 'filedata') {
1881      me.saveHistory(data.fn, data.data, null, 2);
1882      Lexer.FILE_AND_DATA[data.fn] = data.data;
1883      me.parse(data.fn);
1884    } else if (type === 'freshfiledata') {
1885      me.saveHistory(data.fn, data.data, null, 3);
1886      Lexer.FILE_AND_DATA[data.fn] = data.data;
1887    } else if (type === 'whiteCutImg') {
1888      let u8arr = new Uint8Array(data.data);
1889      let imgobj = new Blob([u8arr], { type: 'image/png' });
1890      let wurl = window.URL.createObjectURL(imgobj);
1891      me.initCutData(wurl);
1892    } else if (type === 'circleImg') {
1893      let u8arr = new Uint8Array(data.data);
1894      let imgobj = new Blob([u8arr], { type: 'image/png' });
1895      let wurl = window.URL.createObjectURL(imgobj);
1896      me.initCicleImgData(wurl);
1897    } else if (type === 'cicleOpenImg') {
1898      let u8arr = new Uint8Array(data.data);
1899      let imgobj = new Blob([u8arr], { type: 'image/png' });
1900      let wurl = window.URL.createObjectURL(imgobj);
1901      me.initcicleOpenImgData(wurl);
1902    } else if (type === 'rectangleFocusImg') {
1903      let u8arr = new Uint8Array(data.data);
1904      let imgobj = new Blob([u8arr], { type: 'image/png' });
1905      let wurl = window.URL.createObjectURL(imgobj);
1906      me.initRectangleFocusImgData(wurl);
1907    } else if (type === 'nodeIconImg') {
1908      let u8arr = new Uint8Array(data.data);
1909      let imgobj = new Blob([u8arr], { type: 'image/png' });
1910      let wurl = window.URL.createObjectURL(imgobj);
1911      me.initNodeIconImgData(wurl);
1912    } else if (type === 'attrIconImg') {
1913      let u8arr = new Uint8Array(data.data);
1914      let imgobj = new Blob([u8arr], { type: 'image/png' });
1915      let wurl = window.URL.createObjectURL(imgobj);
1916      me.initAttrIconImgData(wurl);
1917    } else if (type === 'rootIconImg') {
1918      let u8arr = new Uint8Array(data.data);
1919      let imgobj = new Blob([u8arr], { type: 'image/png' });
1920      let wurl = window.URL.createObjectURL(imgobj);
1921      me.initRootIconImgData(wurl);
1922    } else if (type === 'rootIconFocusImg') {
1923      let u8arr = new Uint8Array(data.data);
1924      let imgobj = new Blob([u8arr], { type: 'image/png' });
1925      let wurl = window.URL.createObjectURL(imgobj);
1926      me.initRootIconFocusImgData(wurl);
1927    } else if (type === 'backgroundImg') {
1928      let u8arr = new Uint8Array(data.data);
1929      let imgobj = new Blob([u8arr], { type: 'image/png' });
1930      let wurl = window.URL.createObjectURL(imgobj);
1931      me.initBackgroundImgData(wurl);
1932    } else if (type === 'popItemFocusImg') {
1933      let u8arr = new Uint8Array(data.data);
1934      let imgobj = new Blob([u8arr], { type: 'image/png' });
1935      let wurl = window.URL.createObjectURL(imgobj);
1936      me.initPopItemFocusImgData(wurl);
1937    } else if (type === 'colorThemeChanged') {
1938      me.reloadMenuBgPic();
1939    } else if (type === 'searchBgImg') {
1940      let u8arr = new Uint8Array(data.data);
1941      let imgobj = new Blob([u8arr], { type: 'image/png' });
1942      let wurl = window.URL.createObjectURL(imgobj);
1943      me.initSearchBgImgData(wurl);
1944    } else if (type === 'upCutImg') {
1945      let u8arr = new Uint8Array(data.data);
1946      let imgobj = new Blob([u8arr], { type: 'image/png' });
1947      let wurl = window.URL.createObjectURL(imgobj);
1948      me.initUpImgData(wurl);
1949    } else if (type === 'downCut') {
1950      let u8arr = new Uint8Array(data.data);
1951      let imgobj = new Blob([u8arr], { type: 'image/png' });
1952      let wurl = window.URL.createObjectURL(imgobj);
1953      me.initDownImgData(wurl);
1954    } else if (type === 'closeCutImg') {
1955      let u8arr = new Uint8Array(data.data);
1956      let imgobj = new Blob([u8arr], { type: 'image/png' });
1957      let wurl = window.URL.createObjectURL(imgobj);
1958      me.initCloseImgData(wurl);
1959    } else if (type === 'searchCutImg') {
1960      let u8arr = new Uint8Array(data.data);
1961      let imgobj = new Blob([u8arr], { type: 'image/png' });
1962      let wurl = window.URL.createObjectURL(imgobj);
1963      me.initSearchImgData(wurl);
1964    } else if (type === 'searchNoodRectImg') {
1965      let u8arr = new Uint8Array(data.data);
1966      let imgobj = new Blob([u8arr], { type: 'image/png' });
1967      let wurl = window.URL.createObjectURL(imgobj);
1968      me.initSearchNoodRectImgData(wurl);
1969    } else if (type === 'searchAttrRectImg') {
1970      let u8arr = new Uint8Array(data.data);
1971      let imgobj = new Blob([u8arr], { type: 'image/png' });
1972      let wurl = window.URL.createObjectURL(imgobj);
1973      me.initSearchAttrRectImgData(wurl);
1974    } else {
1975      NapiLog.logError('onReceive is not need');
1976    }
1977  }
1978
1979  initSearchAttrRectImgData(wurl) {
1980    const HEIGHT = 32;
1981    const NEW_WIDTH = 132;
1982    const OLD_WIDTH = 8;
1983    const CS_X_VAL = 8;
1984    const RS_X_VAL = 124;
1985    const CS_OLD_WIDTH = 116;
1986    this.searchAttrCicleImg_ = XTexture.gi().loadTextureFromImage(wurl);
1987    this.leftSearchAttrCicleCut_ = XTexture.gi().makeCut(this.searchAttrCicleImg_, 0, 0, OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
1988    this.centerSearchAttrCut_ = XTexture.gi().makeCut(this.searchAttrCicleImg_, CS_X_VAL, 0, CS_OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
1989    this.rightSearchAttrCicleCut_ = XTexture.gi().makeCut(this.searchAttrCicleImg_, RS_X_VAL, 0, OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
1990  }
1991
1992  initSearchNoodRectImgData(wurl) {
1993    const HEIGHT = 32;
1994    const NEW_WIDTH = 132;
1995    const OLD_WIDTH = 8;
1996    const CS_X_VAL = 8;
1997    const RS_X_VAL = 124;
1998    const CS_OLD_WIDTH = 116;
1999    this.searchRectFocusCicleImg_ = XTexture.gi().loadTextureFromImage(wurl);
2000    this.leftSearchFocusCicleCut_ = XTexture.gi().makeCut(this.searchRectFocusCicleImg_, 0, 0, OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
2001    this.centerSearchCut_ = XTexture.gi().makeCut(this.searchRectFocusCicleImg_, CS_X_VAL, 0, CS_OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
2002    this.rightSearchFocusCicleCut_ = XTexture.gi().makeCut(this.searchRectFocusCicleImg_, RS_X_VAL, 0, OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
2003  }
2004
2005  initSearchImgData(wurl) {
2006    const WIDTH = 16;
2007    const HEIGHT = 16;
2008    this.searchImg_ = XTexture.gi().loadTextureFromImage(wurl);
2009    this.searchCut_ = XTexture.gi().makeCut(this.searchImg_, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT);
2010  }
2011
2012  initCloseImgData(wurl) {
2013    const WIDTH = 16;
2014    const HEIGHT = 16;
2015    this.closeImg_ = XTexture.gi().loadTextureFromImage(wurl);
2016    this.closeCut_ = XTexture.gi().makeCut(this.closeImg_, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT);
2017  }
2018
2019  initDownImgData(wurl) {
2020    const WIDTH = 16;
2021    const HEIGHT = 16;
2022    this.downImg_ = XTexture.gi().loadTextureFromImage(wurl);
2023    this.downCut_ = XTexture.gi().makeCut(this.downImg_, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT);
2024  }
2025
2026  initUpImgData(wurl) {
2027    const WIDTH = 16;
2028    const HEIGHT = 16;
2029    this.upImg_ = XTexture.gi().loadTextureFromImage(wurl);
2030    this.upCut_ = XTexture.gi().makeCut(this.upImg_, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT);
2031  }
2032
2033  initSearchBgImgData(wurl) {
2034    const WIDTH = 494;
2035    const HEIGHT = 56;
2036    this.searchBgImg_ = XTexture.gi().loadTextureFromImage(wurl);
2037    this.searchBgCut_ = XTexture.gi().makeCut(this.searchBgImg_, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT);
2038  }
2039
2040  initPopItemFocusImgData(wurl) {
2041    const WIDTH = 148;
2042    const HEIGHT = 32;
2043    RightMenu.popItemFocusImg_ = XTexture.gi().loadTextureFromImage(wurl);
2044    RightMenu.popItemFocusCut_ = XTexture.gi().makeCut(RightMenu.popItemFocusImg_, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT);
2045  }
2046
2047  initBackgroundImgData(wurl) {
2048    const WIDTH = 156;
2049    const HEIGHT = 112;
2050    RightMenu.backgroundImg_ = XTexture.gi().loadTextureFromImage(wurl);
2051    RightMenu.backgroundCut_ = XTexture.gi().makeCut(RightMenu.backgroundImg_, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT);
2052  }
2053
2054  initRootIconFocusImgData(wurl) {
2055    const WIDTH = 132;
2056    const HEIGHT = 32;
2057    this.rootIconFocusImg_ = XTexture.gi().loadTextureFromImage(wurl);
2058    this.rootIconFocusCut_ = XTexture.gi().makeCut(this.rootIconFocusImg_, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT);
2059  }
2060
2061  initRootIconImgData(wurl) {
2062    const WIDTH = 132;
2063    const HEIGHT = 32;
2064    this.rootIconImg_ = XTexture.gi().loadTextureFromImage(wurl);
2065    this.rootIconCut_ = XTexture.gi().makeCut(this.rootIconImg_, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT);
2066  }
2067
2068  initAttrIconImgData(wurl) {
2069    const WIDTH = 8;
2070    const HEIGHT = 8;
2071    this.attrIconImg_ = XTexture.gi().loadTextureFromImage(wurl);
2072    this.attrIconCut_ = XTexture.gi().makeCut(this.attrIconImg_, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT);
2073  }
2074
2075  initNodeIconImgData(wurl) {
2076    const WIDTH = 8;
2077    const HEIGHT = 8;
2078    this.nodeIconImg_ = XTexture.gi().loadTextureFromImage(wurl);
2079    this.nodeIconCut_ = XTexture.gi().makeCut(this.nodeIconImg_, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT);
2080  }
2081
2082  initcicleOpenImgData(wurl) {
2083    const WIDTH = 20;
2084    const HEIGHT = 20;
2085    this.cicleOpenImg_ = XTexture.gi().loadTextureFromImage(wurl);
2086    this.circleOpenCut_ = XTexture.gi().makeCut(this.cicleOpenImg_, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT);
2087  }
2088
2089  initRectangleFocusImgData(wurl) {
2090    const HEIGHT = 32;
2091    const NEW_WIDTH = 132;
2092    const OLD_WIDTH = 8;
2093    const RF_OLD_WIDTH = 132;
2094    const CF_X_VAL = 8;
2095    const CF_OLD_WIDTH = 116;
2096    const RR_X_VAL = 124;
2097    this.rectangleFocusImg_ = XTexture.gi().loadTextureFromImage(wurl);
2098    this.rectangleFocusCut_ = XTexture.gi().makeCut(this.rectangleFocusImg_, 0, 0, RF_OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
2099    this.leftRectFocusCicleCut_ = XTexture.gi().makeCut(this.rectangleFocusImg_, 0, 0, OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
2100    this.centerFocusCut_ = XTexture.gi().makeCut(this.rectangleFocusImg_, CF_X_VAL, 0, CF_OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
2101    this.rightRectFocusCicleCut_ = XTexture.gi().makeCut(this.rectangleFocusImg_, RR_X_VAL, 0, OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
2102  }
2103
2104  initCicleImgData(wurl) {
2105    const WIDTH = 20;
2106    const HEIGHT = 20;
2107    this.cicleImg_ = XTexture.gi().loadTextureFromImage(wurl);
2108    this.circleCut_ = XTexture.gi().makeCut(this.cicleImg_, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT);
2109  }
2110
2111  initCutData(wurl) {
2112    const HEIGHT = 32;
2113    const NEW_WIDTH = 132;
2114    const OLD_WIDTH = 8;
2115    const CR_X_VAL = 8;
2116    const RR_X_VAL = 124;
2117    const WC_OLD_WIDTH = 132;
2118    const CR_OLD_WIDTH = 116;
2119    this.whiteImg_ = XTexture.gi().loadTextureFromImage(wurl);
2120    this.whiteCut_ = XTexture.gi().makeCut(this.whiteImg_, 0, 0, WC_OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
2121    this.leftRectCicleCut_ = XTexture.gi().makeCut(this.whiteImg_, 0, 0, OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
2122    this.centerRectCut_ = XTexture.gi().makeCut(this.whiteImg_, CR_X_VAL, 0, CR_OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
2123    this.rightRectCicleCut_ = XTexture.gi().makeCut(this.whiteImg_, RR_X_VAL, 0, OLD_WIDTH, HEIGHT, NEW_WIDTH, HEIGHT);
2124  }
2125
2126  syncOpenStatus(newNode, oldParentNode) {
2127    let oldNode = null;
2128    oldParentNode.value_.forEach((item, index) => {
2129      if (newNode.name_ === item.name_) {
2130        oldNode = item;
2131      }
2132    });
2133    if (oldNode === null) {
2134      return;
2135    }
2136    newNode.isOpen_ = oldNode.isOpen_;
2137
2138    if (newNode.type_ === DataType.NODE) {
2139      newNode.value_.forEach((j, index) => {
2140        this.syncOpenStatus(j, oldNode);
2141      });
2142    }
2143  }
2144
2145  syncRootStatus(newRoot, oldRoot) {
2146    newRoot.isOpen_ = oldRoot.isOpen_;
2147    newRoot.value_.forEach((item, index) => {
2148      this.syncOpenStatus(item, oldRoot);
2149    });
2150  }
2151
2152  parse(fn) {
2153    if (this.rootPoint_ === null) {
2154      this.rootPoint_ = fn;
2155    }
2156    let t = Generator.gi().hcsToAst(fn);
2157    if (!t) {
2158      return;
2159    }
2160
2161    let fs = [];
2162    Object.keys(t).forEach((index) => {
2163      let newRoot = Generator.gi().astToObj(t[index].ast.astRoot_);
2164
2165      if (this.files_[index]) {
2166        this.syncRootStatus(newRoot, this.files_[index]);
2167      }
2168
2169      this.files_[index] = newRoot;
2170      fs.push(index);
2171    });
2172
2173    this.filePoint_ = this.rootPoint_;
2174    this.sltInclude.resetList(fs, this.filePoint_);
2175    AttrEditor.gi().setFiles(this.files_);
2176
2177    this.checkAllError();
2178  }
2179
2180  checkAllError() {
2181    NapiLog.clearError();
2182    let n1 = Generator.gi().mergeObj(this.files_);
2183    if (n1) {
2184      n1 = Generator.gi().expandObj(n1);
2185      if (NapiLog.getResult()[0]) {
2186        return true;
2187      }
2188    }
2189    return false;
2190  }
2191}
2192MainEditor.LINE_HEIGHT = 50;
2193MainEditor.NODE_RECT_HEIGHT = 32;
2194MainEditor.NODE_RECT_WIDTH = 132;
2195MainEditor.NODE_TEXT_COLOR = 0xffffffff; // white
2196MainEditor.NODE_TEXT_SIZE = 14;
2197MainEditor.BTN_CONTENT_OFFY = 4;
2198MainEditor.NODE_TEXT_OFFX = 5;
2199MainEditor.NODE_LINE_COLOR = 0xff979797;
2200MainEditor.NODE_SIZE_BG_OFFX = 4;
2201MainEditor.NODE_MORE_CHILD = 20;
2202MainEditor.LINE_WIDTH = 30;
2203MainEditor.LOGO_LEFT_PADDING = 14;
2204MainEditor.LOGO_SIZE = 8;
2205
2206MainEditor.pInstance_ = null;
2207MainEditor.gi = function () {
2208  if (MainEditor.pInstance_ === null) {
2209    MainEditor.pInstance_ = new MainEditor();
2210  }
2211  return MainEditor.pInstance_;
2212};
2213
2214module.exports = {
2215  MainEditor,
2216};
2217