• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device 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
16import { BaseElement, element } from '../../../../../base-ui/BaseElement';
17import { LitTable } from '../../../../../base-ui/table/lit-table';
18import { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar';
19import { FrameChart } from '../../../chart/FrameChart';
20import { SelectionParam } from '../../../../bean/BoxSelection';
21import { ChartMode } from '../../../../bean/FrameChartStruct';
22import { FilterData, TabPaneFilter } from '../TabPaneFilter';
23import { procedurePool } from '../../../../database/Procedure';
24import { MerageBean } from '../../../../database/logic-worker/ProcedureLogicWorkerCommon';
25import { showButtonMenu } from '../SheetUtils';
26import { CallTreeLevelStruct } from '../../../../bean/EbpfStruct';
27import '../../../../../base-ui/headline/lit-headline';
28import { LitHeadLine } from '../../../../../base-ui/headline/lit-headline';
29import { NUM_3, NUM_4 } from '../../../../bean/NumBean';
30import { TabPaneCallTreeHtml } from './TabPaneCallTree.html';
31
32const InvertOptionIndex: number = 0;
33const hideEventOptionIndex: number = 2;
34const hideThreadOptionIndex: number = 3;
35
36@element('tabpane-calltree')
37export class TabPaneCallTree extends BaseElement {
38  public queryFuncName: string = '';
39  public procedureAction: string = '';
40  private callTreeTbl: LitTable | null | undefined;
41  private callTreeTbr: LitTable | null | undefined;
42  private callTreeProgressEL: LitProgressBar | null | undefined;
43  private callTreeRightSource: Array<MerageBean> = [];
44  private callTreeFilter: TabPaneFilter | null | undefined;
45  private callTreeDataSource: unknown[] = [];
46  private callTreeSortKey: string = 'weight';
47  private callTreeSortType: number = 0;
48  private callTreeSelectedData: unknown = undefined;
49  private frameChart: FrameChart | null | undefined;
50  private isChartShow: boolean = false;
51  private systmeRuleName: string = '/system/';
52  private callTreeNumRuleName: string = '/max/min/';
53  private needShowMenu: boolean = true;
54  private searchValue: string = '';
55  private loadingList: number[] = [];
56  private loadingPage: unknown;
57  private currentSelection: SelectionParam | undefined;
58  private flameChartMode: ChartMode = ChartMode.Duration;
59  private currentCallTreeDataSource: Array<MerageBean> = [];
60  private currentRowClickData: unknown;
61  private initWidth: number = 0;
62  private _pieTitle: string = '';
63  private _cWidth: number = 0;
64  private _currentCallTreeLevel: number = 0;
65  private _rowClickData: unknown = undefined;
66  private callTreeLevel: CallTreeLevelStruct | undefined | null;
67  private callTreeHeadLine: LitHeadLine | null | undefined;
68
69  set pieTitle(value: string) {
70    this._pieTitle = value;
71    if (this._pieTitle.length > 0) {
72      this.callTreeHeadLine!.isShow = true;
73      this.callTreeHeadLine!.titleTxt = this._pieTitle;
74      this.callTreeHeadLine!.closeCallback = (): void => {
75        this.restore();
76      };
77    }
78  }
79
80  set cWidth(value: number) {
81    this._cWidth = value;
82  }
83
84  set currentCallTreeLevel(value: number) {
85    this._currentCallTreeLevel = value;
86  }
87
88  set rowClickData(value: unknown) {
89    this._rowClickData = value;
90  }
91
92  set data(callTreeSelection: SelectionParam | unknown) {
93    if (callTreeSelection !== this.currentSelection && this._rowClickData === this.currentRowClickData) {
94      this._rowClickData = undefined;
95    }
96    if (callTreeSelection === this.currentSelection && !this.currentSelection?.isRowClick) {
97      return;
98    }
99    this.searchValue = '';
100    this.initModeAndAction(); // @ts-ignore
101    this.currentSelection = callTreeSelection;
102    this.currentRowClickData = this._rowClickData;
103    this.callTreeTbl!.style.visibility = 'visible';
104    if (this.parentElement!.clientHeight > this.callTreeFilter!.clientHeight) {
105      this.callTreeFilter!.style.display = 'flex';
106    } else {
107      this.callTreeFilter!.style.display = 'none';
108    }
109    procedurePool.submitWithName('logic0', 'fileSystem-reset', [], undefined, () => {});
110    this.callTreeFilter!.initializeFilterTree(true, true, true);
111    this.callTreeFilter!.filterValue = '';
112    this.callTreeProgressEL!.loading = true; // @ts-ignore
113    this.loadingPage.style.visibility = 'visible'; // @ts-ignore
114    this.getDataByWorkAndUpDateCanvas(callTreeSelection);
115  }
116
117  getDataByWorkAndUpDateCanvas(callTreeSelection: SelectionParam): void {
118    if (this.clientWidth === 0) {
119      this.initWidth = this._cWidth;
120    } else {
121      this.initWidth = this.clientWidth;
122    }
123    if (this._rowClickData && this.currentRowClickData !== undefined && this.currentSelection?.isRowClick) {
124      this.getCallTreeDataByPieLevel();
125    } else {
126      this.callTreeHeadLine!.isShow = false;
127      this.getCallTreeData(callTreeSelection, this.initWidth);
128    }
129  }
130
131  private getCallTreeData(callTreeSelection: SelectionParam | unknown, initWidth: number): void {
132    this.getDataByWorker(
133      [
134        {
135          funcName: 'setSearchValue',
136          funcArgs: [''],
137        },
138        {
139          funcName: 'getCurrentDataFromDb', // @ts-ignore
140          funcArgs: [{ queryFuncName: this.queryFuncName, ...callTreeSelection }],
141        },
142      ],
143      (results: unknown[]): void => {
144        this.setLTableData(results);
145        this.callTreeTbr!.recycleDataSource = [];
146        this.frameChart!.mode = this.flameChartMode;
147        this.frameChart?.updateCanvas(true, initWidth); // @ts-ignore
148        this.frameChart!.data = this.callTreeDataSource; // @ts-ignore
149        this.currentCallTreeDataSource = this.callTreeDataSource;
150        this.switchFlameChart();
151        this.callTreeFilter!.icon = 'block';
152      }
153    );
154  }
155
156  /**
157   * 根据Analysis Tab饼图跳转过来的层级绘制对应的CallTree Tab火焰图和表格
158   */
159  private getCallTreeDataByPieLevel(): void {
160    this.callTreeLevel = new CallTreeLevelStruct();
161    this.callTreeLevel = {
162      // @ts-ignore
163      processId: this._rowClickData.pid, // @ts-ignore
164      threadId: this._rowClickData.tid, // @ts-ignore
165      typeId: this._rowClickData.type, // @ts-ignore
166      libId: this._rowClickData.libId, // @ts-ignore
167      symbolId: this._rowClickData.symbolId,
168    };
169    let args = [];
170    args.push({
171      funcName: 'getCurrentDataFromDb',
172      funcArgs: [this.currentSelection, this.callTreeLevel],
173    });
174    // @ts-ignore
175    if (this._rowClickData && this._rowClickData.libId !== undefined && this._currentCallTreeLevel === NUM_3) {
176      // @ts-ignore
177      this.callTreeLevel.libName = this._rowClickData.tableName;
178      args.push({
179        funcName: 'showLibLevelData',
180        funcArgs: [this.callTreeLevel.libId, this.callTreeLevel.libName],
181      });
182    } else if (
183      this._rowClickData && // @ts-ignore
184      this._rowClickData.symbolId !== undefined &&
185      this._currentCallTreeLevel === NUM_4
186    ) {
187      // @ts-ignore
188      this.callTreeLevel.symbolName = this._rowClickData.tableName;
189      args.push({
190        funcName: 'showFunLevelData',
191        funcArgs: [this.callTreeLevel.symbolId, this.callTreeLevel.symbolName],
192      });
193    }
194
195    this.getDataByWorker(args, (results: unknown[]): void => {
196      this.callTreeProgressEL!.loading = false; // @ts-ignore
197      this.loadingPage.style.visibility = 'hidden';
198      this.setLTableData(results);
199      this.callTreeTbr!.recycleDataSource = [];
200      this.frameChart!.mode = this.flameChartMode;
201      this.frameChart?.updateCanvas(true, this.initWidth); // @ts-ignore
202      this.frameChart!.data = this.callTreeDataSource; // @ts-ignore
203      this.currentCallTreeDataSource = this.callTreeDataSource;
204      this.switchFlameChart();
205      this.callTreeFilter!.icon = 'block';
206    });
207  }
208
209  private restore(): void {
210    this.searchValue = '';
211    this.callTreeFilter!.filterValue = '';
212    this.callTreeHeadLine!.isShow = false;
213    this._rowClickData = undefined;
214    this.getCallTreeData(this.currentSelection, this.initWidth);
215  }
216
217  initModeAndAction(): void {
218    if (this.procedureAction === '' && this.hasAttribute('action')) {
219      this.procedureAction = this.getAttribute('action') || '';
220    }
221    if (this.hasAttribute('flame-mode')) {
222      let callTreeFlameMode = this.getAttribute('flame-mode');
223      switch (callTreeFlameMode) {
224        case 'Byte':
225          this.flameChartMode = ChartMode.Byte;
226          break;
227        case 'Count':
228          this.flameChartMode = ChartMode.Count;
229          break;
230        case 'Duration':
231          this.flameChartMode = ChartMode.Duration;
232          break;
233      }
234    }
235    if (this.hasAttribute('query')) {
236      this.queryFuncName = this.getAttribute('query') || '';
237    }
238  }
239
240  getParentTree(callTreeSrc: Array<MerageBean>, target: MerageBean, parents: Array<MerageBean>): boolean {
241    for (let callTreeBean of callTreeSrc) {
242      if (callTreeBean.id === target.id) {
243        parents.push(callTreeBean);
244        return true;
245      } else {
246        if (this.getParentTree(callTreeBean.children as Array<MerageBean>, target, parents)) {
247          parents.push(callTreeBean);
248          return true;
249        }
250      }
251    }
252    return false;
253  }
254
255  getChildTree(callTreeSrc: Array<MerageBean>, id: string, children: Array<MerageBean>): boolean {
256    for (let callTreeBean of callTreeSrc) {
257      if (callTreeBean.id === id && callTreeBean.children.length === 0) {
258        children.push(callTreeBean);
259        return true;
260      } else {
261        if (this.getChildTree(callTreeBean.children as Array<MerageBean>, id, children)) {
262          children.push(callTreeBean);
263          return true;
264        }
265      }
266    }
267    return false;
268  }
269
270  setRightTableData(bean: MerageBean): void {
271    let parents: Array<MerageBean> = [];
272    let children: Array<MerageBean> = []; // @ts-ignore
273    this.getParentTree(this.callTreeDataSource, bean, parents);
274    let maxId: string = bean.id;
275    let maxDur: number = 0;
276
277    function findMaxStack(bean: MerageBean): void {
278      if (bean.children.length === 0) {
279        if (bean.dur > maxDur) {
280          maxDur = bean.dur;
281          maxId = bean.id;
282        }
283      } else {
284        bean.children.map((callChild: unknown) => {
285          findMaxStack(<MerageBean>callChild);
286        });
287      }
288    }
289
290    findMaxStack(bean);
291    this.getChildTree(bean.children as Array<MerageBean>, maxId, children);
292    let callTreeArr = parents.reverse().concat(children.reverse());
293    for (let data of callTreeArr) {
294      data.type = data.lib.endsWith('.so.1') || data.lib.endsWith('.dll') || data.lib.endsWith('.so') ? 0 : 1;
295    }
296    let len = callTreeArr.length;
297    this.callTreeRightSource = callTreeArr;
298    this.callTreeTbr!.dataSource = len === 0 ? [] : callTreeArr;
299  }
300
301  connectedCallback(): void {
302    this.parentElement!.onscroll = (): void => {
303      this.frameChart!.tabPaneScrollTop = this.parentElement!.scrollTop;
304    };
305    this.frameChart!.addChartClickListener((needShowMenu: boolean) => {
306      this.parentElement!.scrollTo(0, 0);
307      showButtonMenu(this.callTreeFilter, needShowMenu);
308      this.needShowMenu = needShowMenu;
309    });
310    let filterHeight = 0;
311    new ResizeObserver((entries: ResizeObserverEntry[]): void => {
312      let callTreeTabFilter = this.shadowRoot!.querySelector('#filter') as HTMLElement;
313      if (callTreeTabFilter.clientHeight > 0) {
314        filterHeight = callTreeTabFilter.clientHeight;
315      }
316      if (this.parentElement!.clientHeight > filterHeight) {
317        callTreeTabFilter.style.display = 'flex';
318      } else {
319        callTreeTabFilter.style.display = 'none';
320      }
321      if (this.callTreeTbl!.style.visibility === 'hidden') {
322        callTreeTabFilter.style.display = 'none';
323      }
324      if (this.parentElement?.clientHeight !== 0) {
325        if (this.isChartShow) {
326          this.frameChart?.updateCanvas(false, entries[0].contentRect.width);
327          this.frameChart?.calculateChartData();
328        }
329        let headLineHeight = 0;
330        if (this.callTreeHeadLine?.isShow) {
331          headLineHeight = this.callTreeHeadLine!.clientHeight;
332        }
333        if (this.callTreeTbl) {
334          // @ts-ignore
335          this.callTreeTbl.shadowRoot.querySelector('.table').style.height = `${
336            this.parentElement!.clientHeight - 10 - 35 - headLineHeight
337          }px`;
338          this.callTreeTbl.reMeauseHeight();
339        }
340        if (this.callTreeTbr) {
341          // @ts-ignore
342          this.callTreeTbr.shadowRoot.querySelector('.table').style.height = `${
343            this.parentElement!.clientHeight - 45 - 21 - headLineHeight
344          }px`;
345          this.callTreeTbr.reMeauseHeight();
346        } // @ts-ignore
347        this.loadingPage.style.height = `${this.parentElement!.clientHeight - 24}px`;
348      }
349    }).observe(this.parentElement!);
350  }
351
352  initElements(): void {
353    this.callTreeHeadLine = this.shadowRoot?.querySelector<LitHeadLine>('.titleBox');
354    this.callTreeTbl = this.shadowRoot?.querySelector<LitTable>('#tb-calltree');
355    this.callTreeProgressEL = this.shadowRoot?.querySelector('.call-tree-progress') as LitProgressBar;
356    this.frameChart = this.shadowRoot?.querySelector<FrameChart>('#framechart');
357    this.loadingPage = this.shadowRoot?.querySelector('.call-tree-loading');
358    this.callTreeTbl!.rememberScrollTop = true;
359    this.callTreeFilter = this.shadowRoot?.querySelector<TabPaneFilter>('#filter');
360    this.callTreeFilter!.disabledTransfer(true);
361    this.addEventListener('contextmenu', (event): void => {
362      event.preventDefault(); // 阻止默认的上下文菜单弹框
363    });
364    this.rowClickEvent();
365    let boundFilterFunc = this.filterFunc.bind(this);
366    this.callTreeFilter!.getDataLibrary(boundFilterFunc);
367    this.callTreeFilter!.getDataMining(boundFilterFunc);
368    this.handleCallTreeData();
369    this.handleConstraintsData();
370    this.handleFilterData();
371    this.callTreeColumnClick();
372  }
373
374  private filterFunc(data: unknown): void {
375    let callTreeFuncArgs: unknown[] = []; // @ts-ignore
376    if (data.type === 'check') {
377      this.handleCheckType(data, callTreeFuncArgs); // @ts-ignore
378    } else if (data.type === 'select') {
379      this.handleSelectType(callTreeFuncArgs, data); // @ts-ignore
380    } else if (data.type === 'button') {
381      // @ts-ignore
382      if (data.item === 'symbol') {
383        // @ts-ignore
384        if (this.callTreeSelectedData && !this.callTreeSelectedData.canCharge) {
385          return;
386        }
387        if (this.callTreeSelectedData !== undefined) {
388          this.handleSymbolCase(data, callTreeFuncArgs);
389        } else {
390          return;
391        } // @ts-ignore
392      } else if (data.item === 'library') {
393        // @ts-ignore
394        if (this.callTreeSelectedData && !this.callTreeSelectedData.canCharge) {
395          return;
396        } // @ts-ignore
397        if (this.callTreeSelectedData !== undefined && this.callTreeSelectedData.lib !== '') {
398          this.handleLibraryCase(data, callTreeFuncArgs);
399        } else {
400          return;
401        } // @ts-ignore
402      } else if (data.item === 'restore') {
403        this.handleRestoreCase(data, callTreeFuncArgs);
404      }
405    }
406    this.performDataProcessing(callTreeFuncArgs);
407  }
408
409  private handleLibraryCase(data: unknown, callTreeFuncArgs: unknown[]): void {
410    // @ts-ignore
411    this.callTreeFilter!.addDataMining({ name: this.callTreeSelectedData.lib }, data.item);
412    callTreeFuncArgs.push({
413      funcName: 'splitTree', // @ts-ignore
414      funcArgs: [this.callTreeSelectedData.lib, false, false],
415    });
416  }
417
418  private handleSymbolCase(data: unknown, callTreeFuncArgs: unknown[]): void {
419    // @ts-ignore
420    this.callTreeFilter!.addDataMining({ name: this.callTreeSelectedData.symbol }, data.item);
421    callTreeFuncArgs.push({
422      funcName: 'splitTree', // @ts-ignore
423      funcArgs: [this.callTreeSelectedData.symbol, false, true],
424    });
425  }
426
427  private callTreeColumnClick(): void {
428    this.callTreeTbl!.addEventListener('column-click', (evt: Event): void => {
429      // @ts-ignore
430      this.callTreeSortKey = evt.detail.key;
431      // @ts-ignore
432      this.callTreeSortType = evt.detail.sort;
433      // @ts-ignore
434      this.setLTableData(this.callTreeDataSource); // @ts-ignore
435      this.frameChart!.data = this.callTreeDataSource;
436    });
437  }
438
439  private performDataProcessing(callTreeFuncArgs: unknown[]): void {
440    this.getDataByWorker(callTreeFuncArgs, (result: unknown[]): void => {
441      this.setLTableData(result); // @ts-ignore
442      this.frameChart!.data = this.callTreeDataSource;
443      if (this.isChartShow) {
444        this.frameChart?.calculateChartData();
445      }
446      this.callTreeTbl!.move1px();
447      if (this.callTreeSelectedData) {
448        // @ts-ignore
449        this.callTreeSelectedData.isSelected = false;
450        this.callTreeTbl?.clearAllSelection(this.callTreeSelectedData);
451        this.callTreeTbr!.recycleDataSource = [];
452        this.callTreeSelectedData = undefined;
453      }
454    });
455  }
456
457  private handleRestoreCase(data: unknown, callTreeFuncArgs: unknown[]): void {
458    // @ts-ignore
459    if (data.remove !== undefined && data.remove.length > 0) {
460      // @ts-ignore
461      let list = data.remove.map((item: unknown) => {
462        // @ts-ignore
463        return item.name;
464      });
465      callTreeFuncArgs.push({
466        funcName: 'resotreAllNode',
467        funcArgs: [list],
468      });
469      callTreeFuncArgs.push({
470        funcName: 'resetAllNode',
471        funcArgs: [],
472      });
473      list.forEach((symbol: string) => {
474        callTreeFuncArgs.push({
475          funcName: 'clearSplitMapData',
476          funcArgs: [symbol],
477        });
478      });
479    }
480  }
481
482  private handleFilterData(): void {
483    this.callTreeFilter!.getFilterData((callTreeFilterData: FilterData) => {
484      if (
485        (this.isChartShow && callTreeFilterData.icon === 'tree') ||
486        (!this.isChartShow && callTreeFilterData.icon === 'block')
487      ) {
488        this.switchFlameChart(callTreeFilterData);
489      } else if (this.searchValue !== this.callTreeFilter!.filterValue) {
490        this.searchValue = this.callTreeFilter!.filterValue;
491        let callTreeArgs = [
492          {
493            funcName: 'setSearchValue',
494            funcArgs: [this.searchValue],
495          },
496          {
497            funcName: 'resetAllNode',
498            funcArgs: [],
499          },
500        ];
501        this.getDataByWorker(callTreeArgs, (result: unknown[]): void => {
502          this.callTreeTbl!.isSearch = true;
503          this.callTreeTbl!.setStatus(result, true);
504          this.setLTableData(result); // @ts-ignore
505          this.frameChart!.data = this.callTreeDataSource;
506          this.switchFlameChart(callTreeFilterData);
507        });
508      } else {
509        this.callTreeTbl!.setStatus(this.callTreeDataSource, true);
510        this.setLTableData(this.callTreeDataSource);
511        this.switchFlameChart(callTreeFilterData);
512      }
513    });
514  }
515
516  private handleConstraintsData(): void {
517    this.callTreeFilter!.getCallTreeConstraintsData((data: unknown) => {
518      let callTreeConstraintsArgs: unknown[] = [
519        {
520          funcName: 'resotreAllNode',
521          funcArgs: [[this.callTreeNumRuleName]],
522        },
523        {
524          funcName: 'clearSplitMapData',
525          funcArgs: [this.callTreeNumRuleName],
526        },
527      ]; // @ts-ignore
528      if (data.checked) {
529        callTreeConstraintsArgs.push({
530          funcName: 'hideNumMaxAndMin', // @ts-ignore
531          funcArgs: [parseInt(data.min), data.max],
532        });
533      }
534      callTreeConstraintsArgs.push({
535        funcName: 'resetAllNode',
536        funcArgs: [],
537      });
538      this.getDataByWorker(callTreeConstraintsArgs, (result: unknown[]) => {
539        this.setLTableData(result); // @ts-ignore
540        this.frameChart!.data = this.callTreeDataSource;
541        if (this.isChartShow) {
542          this.frameChart?.calculateChartData();
543        }
544      });
545    });
546  }
547
548  private handleCallTreeData(): void {
549    this.callTreeFilter!.getCallTreeData((data: unknown) => {
550      // @ts-ignore
551      if ([InvertOptionIndex, hideThreadOptionIndex, hideEventOptionIndex].includes(data.value)) {
552        this.refreshAllNode({
553          ...this.callTreeFilter!.getFilterTreeData(), // @ts-ignore
554          callTree: data.checks,
555        });
556      } else {
557        let callTreeArgs: unknown[] = []; // @ts-ignore
558        if (data.checks[1]) {
559          callTreeArgs.push({
560            funcName: 'hideSystemLibrary',
561            funcArgs: [true],
562          });
563          callTreeArgs.push({
564            funcName: 'resetAllNode',
565            funcArgs: [],
566          });
567        } else {
568          callTreeArgs.push({
569            funcName: 'resotreAllNode',
570            funcArgs: [[this.systmeRuleName]],
571          });
572          callTreeArgs.push({
573            funcName: 'resetAllNode',
574            funcArgs: [],
575          });
576          callTreeArgs.push({
577            funcName: 'clearSplitMapData',
578            funcArgs: [this.systmeRuleName],
579          });
580        }
581        this.getDataByWorker(callTreeArgs, (result: unknown[]) => {
582          this.setLTableData(result); // @ts-ignore
583          this.frameChart!.data = this.callTreeDataSource;
584          if (this.isChartShow) {
585            this.frameChart?.calculateChartData();
586          }
587        });
588      }
589    });
590  }
591
592  private handleSelectType(callTreeFuncArgs: unknown[], data: unknown): void {
593    callTreeFuncArgs.push({
594      funcName: 'resotreAllNode', // @ts-ignore
595      funcArgs: [[data.item.name]],
596    });
597    callTreeFuncArgs.push({
598      funcName: 'clearSplitMapData', // @ts-ignore
599      funcArgs: [data.item.name],
600    });
601    callTreeFuncArgs.push({
602      funcName: 'splitTree', // @ts-ignore
603      funcArgs: [data.item.name, data.item.select === '0', data.item.type === 'symbol'],
604    });
605  }
606
607  private handleCheckType(data: unknown, callTreeFuncArgs: unknown[]): void {
608    // @ts-ignore
609    if (data.item.checked) {
610      callTreeFuncArgs.push({
611        funcName: 'splitTree', // @ts-ignore
612        funcArgs: [data.item.name, data.item.select === '0', data.item.type === 'symbol'],
613      });
614    } else {
615      callTreeFuncArgs.push({
616        funcName: 'resotreAllNode', // @ts-ignore
617        funcArgs: [[data.item.name]],
618      });
619      callTreeFuncArgs.push({
620        funcName: 'resetAllNode',
621        funcArgs: [],
622      });
623      callTreeFuncArgs.push({
624        funcName: 'clearSplitMapData', // @ts-ignore
625        funcArgs: [data.item.name],
626      });
627    }
628  }
629
630  private rowClickEvent(): void {
631    this.callTreeTbl!.addEventListener('row-click', (evt: unknown) => {
632      // @ts-ignore
633      let data = evt.detail.data as MerageBean;
634      document.dispatchEvent(
635        new CustomEvent('number_calibration', {
636          detail: { time: data.tsArray, durations: data.durArray },
637        })
638      );
639      this.setRightTableData(data);
640      data.isSelected = true;
641      this.callTreeSelectedData = data;
642      this.callTreeTbr?.clearAllSelection(data);
643      this.callTreeTbr?.setCurrentSelection(data);
644      // @ts-ignore
645      if ((evt.detail as unknown).callBack) {
646        // @ts-ignore
647        (evt.detail as unknown).callBack(true);
648      }
649    });
650    this.callTreeTbr = this.shadowRoot?.querySelector<LitTable>('#tb-list');
651    this.callTreeTbr!.addEventListener('row-click', (evt: unknown): void => {
652      // @ts-ignore
653      let data = evt.detail.data as MerageBean;
654      this.callTreeTbl?.clearAllSelection(data); // @ts-ignore
655      (data as unknown).isSelected = true;
656      this.callTreeTbl!.scrollToData(data);
657      // @ts-ignore
658      if ((evt.detail as unknown).callBack) {
659        // @ts-ignore
660        (evt.detail as unknown).callBack(true);
661      }
662    });
663  }
664
665  switchFlameChart(data?: unknown): void {
666    let callTreePageTab = this.shadowRoot?.querySelector('#show_table');
667    let callTreePageChart = this.shadowRoot?.querySelector('#show_chart'); // @ts-ignore
668    if (!data || data.icon === 'block') {
669      callTreePageChart?.setAttribute('class', 'show');
670      callTreePageTab?.setAttribute('class', '');
671      this.isChartShow = true;
672      this.callTreeFilter!.disabledMining = true;
673      showButtonMenu(this.callTreeFilter, this.needShowMenu);
674      this.frameChart?.calculateChartData(); // @ts-ignore
675    } else if (data.icon === 'tree') {
676      callTreePageChart?.setAttribute('class', '');
677      callTreePageTab?.setAttribute('class', 'show');
678      showButtonMenu(this.callTreeFilter, true);
679      this.isChartShow = false;
680      this.callTreeFilter!.disabledMining = false;
681      this.frameChart!.clearCanvas();
682      this.callTreeTbl!.reMeauseHeight();
683    }
684  }
685
686  refreshAllNode(filterData: unknown): void {
687    let callTreeArgs: unknown[] = []; // @ts-ignore
688    let isTopDown: boolean = !filterData.callTree[0]; // @ts-ignore
689    let isHideSystemLibrary = filterData.callTree[1]; // @ts-ignore
690    let isHideEvent: boolean = filterData.callTree[2]; // @ts-ignore
691    let isHideThread: boolean = filterData.callTree[3]; // @ts-ignore
692    let list = filterData.dataMining.concat(filterData.dataLibrary);
693    callTreeArgs.push({ funcName: 'hideThread', funcArgs: [isHideThread] });
694    callTreeArgs.push({ funcName: 'hideEvent', funcArgs: [isHideEvent] });
695    callTreeArgs.push({ funcName: 'getCallChainsBySampleIds', funcArgs: [isTopDown, this.queryFuncName] });
696    this.callTreeTbr!.recycleDataSource = [];
697    if (isHideSystemLibrary) {
698      callTreeArgs.push({ funcName: 'hideSystemLibrary', funcArgs: [true] });
699    } // @ts-ignore
700    if (filterData.callTreeConstraints.checked) {
701      callTreeArgs.push({
702        funcName: 'hideNumMaxAndMin', // @ts-ignore
703        funcArgs: [parseInt(filterData.callTreeConstraints.inputs[0]), filterData.callTreeConstraints.inputs[1]],
704      });
705    }
706    callTreeArgs.push({ funcName: 'splitAllProcess', funcArgs: [list] });
707    callTreeArgs.push({
708      funcName: 'resetAllNode',
709      funcArgs: [],
710    }); // @ts-ignore
711    if (this._rowClickData && this._rowClickData.libId !== undefined && this._currentCallTreeLevel === 3) {
712      callTreeArgs.push({
713        funcName: 'showLibLevelData',
714        funcArgs: [this.callTreeLevel!.libId, this.callTreeLevel!.libName],
715      }); // @ts-ignore
716    } else if (this._rowClickData && this._rowClickData.symbolId !== undefined && this._currentCallTreeLevel === 4) {
717      callTreeArgs.push({
718        funcName: 'showFunLevelData',
719        funcArgs: [this.callTreeLevel!.symbolId, this.callTreeLevel!.symbolName],
720      });
721    }
722    this.getDataByWorker(callTreeArgs, (result: unknown[]): void => {
723      this.setLTableData(result); // @ts-ignore
724      this.frameChart!.data = this.callTreeDataSource;
725      if (this.isChartShow) {
726        this.frameChart?.calculateChartData();
727      }
728    });
729  }
730
731  setLTableData(resultData: unknown[]): void {
732    this.callTreeDataSource = this.sortCallFnTree(resultData);
733    this.callTreeTbl!.recycleDataSource = this.callTreeDataSource;
734  }
735
736  sortCallFnTree(arr: Array<unknown>): Array<unknown> {
737    let sortArr = arr.sort((compareFnA: unknown, compareFnB: unknown): number => {
738      if (this.callTreeSortKey === 'self') {
739        if (this.callTreeSortType === 0) {
740          // @ts-ignore
741          return compareFnB.dur - compareFnA.dur;
742        } else if (this.callTreeSortType === 1) {
743          // @ts-ignore
744          return compareFnA.selfDur - compareFnB.selfDur;
745        } else {
746          // @ts-ignore
747          return compareFnB.selfDur - compareFnA.selfDur;
748        }
749      } else {
750        if (this.callTreeSortType === 0) {
751          // @ts-ignore
752          return compareFnB.dur - compareFnA.dur;
753        } else if (this.callTreeSortType === 1) {
754          // @ts-ignore
755          return compareFnA.dur - compareFnB.dur;
756        } else {
757          // @ts-ignore
758          return compareFnB.dur - compareFnA.dur;
759        }
760      }
761    });
762    sortArr.map((call: unknown): void => {
763      // @ts-ignore
764      call.children = this.sortCallFnTree(call.children);
765    });
766    return sortArr;
767  }
768
769  getDataByWorker(args: unknown[], handler: Function): void {
770    this.loadingList.push(1); // @ts-ignore
771    this.loadingPage.style.visibility = 'visible';
772    this.callTreeProgressEL!.loading = true;
773    procedurePool.submitWithName(
774      'logic0',
775      this.procedureAction,
776      { args, callType: this.queryFuncName },
777      undefined,
778      (callTreeResults: unknown): void => {
779        handler(callTreeResults);
780        this.loadingList.splice(0, 1);
781        if (this.loadingList.length === 0) {
782          this.callTreeProgressEL!.loading = false; // @ts-ignore
783          this.loadingPage.style.visibility = 'hidden';
784        }
785      }
786    );
787  }
788
789  initHtml(): string {
790    return TabPaneCallTreeHtml;
791  }
792}
793