• 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 { element } from '../../../../base-ui/BaseElement';
17import { TimeRange } from '../timer-shaft/RangeRuler';
18import '../../../../base-ui/icon/LitIcon';
19import { Rect } from '../timer-shaft/Rect';
20import { BaseStruct } from '../../../bean/BaseStruct';
21import { ns2x } from '../TimerShaftElement';
22import { TraceRowObject } from './TraceRowObject';
23import { LitCheckBox } from '../../../../base-ui/checkbox/LitCheckBox';
24import { LitIcon } from '../../../../base-ui/icon/LitIcon';
25import '../../../../base-ui/popover/LitPopoverV';
26import '../../../../base-ui/tree/LitTree';
27import { LitPopover } from '../../../../base-ui/popover/LitPopoverV';
28import { info } from '../../../../log/Log';
29import { ColorUtils } from './ColorUtils';
30import { drawSelectionRange, isFrameContainPoint } from '../../../database/ui-worker/ProcedureWorkerCommon';
31import { TraceRowConfig } from './TraceRowConfig';
32import { type TreeItemData, LitTree } from '../../../../base-ui/tree/LitTree';
33import { SpSystemTrace } from '../../SpSystemTrace';
34import { TraceRowHtml } from './TraceRow.html';
35
36export class RangeSelectStruct {
37  startX: number | undefined;
38  endX: number | undefined;
39  startNS: number | undefined;
40  endNS: number | undefined;
41}
42
43let collectList: Array<TraceRow<BaseStruct>> = [];
44let rowDragId: string | undefined | null;
45let dragDirection: string = '';
46
47@element('trace-row')
48export class TraceRow<T extends BaseStruct> extends HTMLElement {
49  sharedArrayBuffers: unknown;
50  intersectionRatio: number = 0;
51  static ROW_TYPE_SPSEGNENTATION = 'spsegmentation';
52  static ROW_TYPE_CPU_COMPUTILITY = 'cpu-computility';
53  static ROW_TYPE_GPU_COMPUTILITY = 'gpu-computility';
54  static ROW_TYPE_BINDER_COUNT = 'binder-count';
55  static ROW_TYPE_SCHED_SWITCH = 'sched-switch';
56  static ROW_TYPE_CPU = 'cpu-data';
57  static ROW_TYPE_CPU_STATE = 'cpu-state';
58  static ROW_TYPE_CPU_FREQ = 'cpu-freq';
59  static ROW_TYPE_CPU_FREQ_LIMIT = 'cpu-limit-freq';
60  static ROW_TYPE_CPU_FREQ_ALL = 'cpu-frequency';
61  static ROW_TYPE_CPU_STATE_ALL = 'cpu-State';
62  static ROW_TYPE_CPU_FREQ_LIMITALL = 'cpu-frequency-limit';
63  static ROW_TYPE_FPS = 'fps';
64  static ROW_TYPE_NATIVE_MEMORY = 'native-memory';
65  static ROW_TYPE_HIPERF = 'hiperf';
66  static ROW_TYPE_DELIVER_INPUT_EVENT = 'DeliverInputEvent';
67  static ROW_TYPE_HIPERF_CPU = 'hiperf-cpu';
68  static ROW_TYPE_PERF_CALLCHART = 'hiperf-callchart';
69  static ROW_TYPE_HIPERF_PROCESS = 'hiperf-process';
70  static ROW_TYPE_HIPERF_THREAD = 'hiperf-thread';
71  static ROW_TYPE_HIPERF_REPORT = 'hiperf-report';
72  static ROW_TYPE_HIPERF_EVENT = 'hiperf-event';
73  static ROW_TYPE_PROCESS = 'process';
74  static ROW_TYPE_APP_STARTUP = 'app-startup';
75  static ROW_TYPE_STATIC_INIT = 'static-init';
76  static ROW_TYPE_THREAD = 'thread';
77  static ROW_TYPE_MEM = 'mem';
78  static ROW_TYPE_VIRTUAL_MEMORY_GROUP = 'virtual-memory-group';
79  static ROW_TYPE_VIRTUAL_MEMORY = 'virtual-memory-cell';
80  static ROW_TYPE_FILE_SYSTEM_GROUP = 'file-system-group';
81  static ROW_TYPE_FILE_SYSTEM = 'file-system-cell';
82  static ROW_TYPE_HEAP = 'heap';
83  static ROW_TYPE_ARK_TS = 'ark-ts';
84  static ROW_TYPE_HEAP_SNAPSHOT = 'heap-snapshot';
85  static ROW_TYPE_HEAP_TIMELINE = 'heap-timeline';
86  static ROW_TYPE_FUNC = 'func';
87  static ROW_TYPE_MONITOR = 'ability-monitor';
88  static ROW_TYPE_CPU_ABILITY = 'cpu-ability';
89  static ROW_TYPE_MEMORY_ABILITY = 'memory-ability';
90  static ROW_TYPE_DISK_ABILITY = 'disk-ability';
91  static ROW_TYPE_NETWORK_ABILITY = 'network-ability';
92  static ROW_TYPE_DMA_ABILITY = 'dma-ability';
93  static ROW_TYPE_GPU_MEMORY_ABILITY = 'gpu-memory-ability';
94  static ROW_TYPE_SDK = 'sdk';
95  static ROW_TYPE_SDK_COUNTER = 'sdk-counter';
96  static ROW_TYPE_SDK_SLICE = 'sdk-slice';
97  static ROW_TYPE_ENERGY = 'energy';
98  static ROW_TYPE_ANOMALY_ENERGY = 'anomaly-energy';
99  static ROW_TYPE_SYSTEM_ENERGY = 'system-energy';
100  static ROW_TYPE_POWER_ENERGY = 'power-energy';
101  static ROW_TYPE_STATE_ENERGY = 'state-energy';
102  static ROW_TYPE_SYS_MEMORY_GPU = 'sys-memory-gpu';
103  static ROW_TYPE_SYS_MEMORY_GPU_GL = 'sys-memory-gpu-gl';
104  static ROW_TYPE_SYS_MEMORY_GPU_GRAPH = 'sys-memory-gpu-graph';
105  static ROW_TYPE_SYS_MEMORY_GPU_TOTAL = 'sys-memory-gpu-total';
106  static ROW_TYPE_SYS_MEMORY_GPU_WINDOW = 'sys-memory-gpu-window';
107  static ROW_TYPE_VM_TRACKER_SMAPS = 'smaps';
108  static ROW_TYPE_VM_TRACKER = 'VmTracker';
109  static ROW_TYPE_DMA_VMTRACKER = 'dma-vmTracker';
110  static ROW_TYPE_GPU_MEMORY_VMTRACKER = 'gpu-memory-vmTracker';
111  static ROW_TYPE_GPU_RESOURCE_VMTRACKER = 'sys-memory-gpu-resource';
112  static ROW_TYPE_VMTRACKER_SHM = 'VmTracker-shm';
113  static ROW_TYPE_CLOCK_GROUP = 'clock-group';
114  static ROW_TYPE_COLLECT_GROUP = 'collect-group';
115  static ROW_TYPE_CLOCK = 'clock';
116  static ROW_TYPE_IRQ_GROUP = 'irq-group';
117  static ROW_TYPE_IRQ = 'irq';
118  static ROW_TYPE_JANK = 'janks';
119  static ROW_TYPE_FRAME = 'frame';
120  static ROW_TYPE_FRAME_ANIMATION = 'frame-animation';
121  static ROW_TYPE_FRAME_DYNAMIC = 'frame-dynamic';
122  static ROW_TYPE_FRAME_SPACING = 'frame-spacing';
123  static ROW_TYPE_JS_CPU_PROFILER = 'js-cpu-profiler-cell';
124  static ROW_TYPE_PURGEABLE_TOTAL_ABILITY = 'purgeable-total-ability';
125  static ROW_TYPE_PURGEABLE_PIN_ABILITY = 'purgeable-pin-ability';
126  static ROW_TYPE_PURGEABLE_TOTAL_VM = 'purgeable-total-vm';
127  static ROW_TYPE_PURGEABLE_PIN_VM = 'purgeable-pin-vm';
128  static ROW_TYPE_LOGS = 'logs';
129  static ROW_TYPE_SAMPLE = 'bpftrace';
130  static ROW_TYPE_ALL_APPSTARTUPS = 'all-appstartups';
131  static ROW_TYPE_PERF_TOOL_GROUP = 'perf-tool-group';
132  static ROW_TYPE_PERF_TOOL = 'perf-tool';
133  static FRAME_WIDTH: number = 0;
134  static range: TimeRange | undefined | null;
135  static rangeSelectObject: RangeSelectStruct | undefined;
136  static ROW_TYPE_HI_SYSEVENT = 'hi-sysevent'; // @ts-ignore
137  public obj: TraceRowObject<unknown> | undefined | null;
138  isHover: boolean = false;
139  hoverX: number = 0;
140  hoverY: number = 0;
141  index: number = 0;
142  public must: boolean = false;
143  public isTransferCanvas = false;
144  onComplete: Function | undefined;
145  isComplete: boolean = false;
146  public dataList: Array<T> = [];
147  public dataList2: Array<T> = [];
148  public dataListCache: Array<T> = [];
149  public fixedList: Array<T> = [];
150  public sliceCache: number[] = [-1, -1];
151  public describeEl: HTMLElement | null | undefined;
152  public canvas: Array<HTMLCanvasElement> = [];
153  public canvasVessel: HTMLDivElement | null | undefined;
154  public tipEL: HTMLDivElement | null | undefined;
155  public checkBoxEL: LitCheckBox | null | undefined;
156  public collectEL: LitIcon | null | undefined;
157  public onThreadHandler: ((useCache: boolean, buf: ArrayBuffer | undefined | null) => void) | undefined | null;
158  public onRowSettingChangeHandler: ((keys: Array<string>, nodes: Array<unknown>) => void) | undefined | null;
159  public onRowCheckFileChangeHandler: (() => void) | undefined | null;
160  public supplier: (() => Promise<Array<T>>) | undefined | null; // @ts-ignore
161  public favoriteChangeHandler: ((fav: TraceRow<unknown>) => void) | undefined | null; // @ts-ignore
162  public selectChangeHandler: ((traceRow: TraceRow<unknown>) => void) | undefined | null;
163  dpr = window.devicePixelRatio || 1;
164  // @ts-ignore
165  offscreen: Array<OffscreenCanvas | undefined> = [];
166  canvasWidth = 0;
167  canvasHeight = 0;
168  private _collectGroup: string | undefined;
169  public _frame: Rect | undefined;
170  public isLoading: boolean = false;
171  public tampName: string = '';
172  public readonly args: unknown;
173  public templateType: Set<string> = new Set<string>();
174  private rootEL: HTMLDivElement | null | undefined;
175  private nameEL: HTMLLabelElement | null | undefined;
176  private rowSettingTree: LitTree | null | undefined;
177  private rowSettingPop: LitPopover | null | undefined;
178  private fileEL: unknown;
179  private rowCheckFilePop: LitPopover | null | undefined;
180  private _rangeSelect: boolean = false;
181  private _drawType: number = 0;
182  private _enableCollapseChart: boolean = false;
183  online: boolean = false;
184  static isUserInteraction: boolean;
185  asyncFuncName: string | undefined | null;
186  asyncFuncNamePID: number | undefined | null;
187  translateY: number = 0; //single canvas offsetY;
188  // @ts-ignore
189  childrenList: Array<TraceRow<unknown>> = []; // @ts-ignore
190  parentRowEl: TraceRow<unknown> | undefined;
191  _rowSettingList: Array<TreeItemData> | null | undefined;
192  public supplierFrame: (() => Promise<Array<T>>) | undefined | null; //实时查询
193  public getCacheData: ((arg: unknown) => Promise<Array<unknown>> | undefined) | undefined; //实时查询
194  public loadingFrame: boolean = false; //实时查询,正在查询中
195  public needRefresh: boolean = true;
196  _frameRateList: Array<number> | undefined; //存储平均帧率数据
197  _avgRateTxt: string | undefined | null; //存储帧率显示文字
198  public folderIcon: LitIcon | null | undefined;
199  private sampleUploadEl: HTMLDivElement | null | undefined;
200  private jsonFileEl: HTMLInputElement | null | undefined;
201
202  focusHandler?: (ev: MouseEvent) => void | undefined;
203  findHoverStruct?: () => void | undefined;
204  public funcMaxHeight: number = 0;
205  currentContext: CanvasRenderingContext2D | undefined | null;
206  static ROW_TYPE_LTPO: string | null | undefined;
207  static ROW_TYPE_HITCH_TIME: string | null | undefined;
208
209  constructor(
210    args: {
211      canvasNumber: number;
212      alpha: boolean;
213      contextId: string;
214      isOffScreen: boolean;
215      skeleton?: boolean;
216    } = {
217      canvasNumber: 1,
218      alpha: false,
219      contextId: '2d',
220      isOffScreen: true,
221      skeleton: false,
222    }
223  ) {
224    super();
225    this.args = args;
226    this.attachShadow({ mode: 'open' }).innerHTML = this.initHtml();
227    this.initElements();
228  }
229
230  static skeleton<T extends BaseStruct>(): TraceRow<T> {
231    let tr = new TraceRow<T>({
232      alpha: false,
233      canvasNumber: 0,
234      contextId: '',
235      isOffScreen: false,
236      skeleton: true,
237    });
238    tr.isTransferCanvas = true;
239    return tr;
240  }
241
242  static get observedAttributes(): string[] {
243    return [
244      'folder',
245      'sticky',
246      'name',
247      'expansion',
248      'children',
249      'height',
250      'row-type',
251      'row-id',
252      'row-parent-id',
253      'sleeping',
254      'check-type',
255      'collect-type',
256      'collect-group',
257      'disabled-check',
258      'row-discard',
259      'func-expand',
260      'row-setting',
261      'row-setting-list',
262      'row-setting-popover-direction',
263    ];
264  }
265
266  get uploadEl(): HTMLDivElement | null | undefined {
267    return this.sampleUploadEl;
268  }
269
270  get frameRateList(): Array<number> | undefined {
271    return this._frameRateList;
272  }
273
274  set frameRateList(value: Array<number> | undefined) {
275    this._frameRateList = value;
276  }
277
278  get avgRateTxt(): string | undefined | null {
279    return this._avgRateTxt;
280  }
281
282  set avgRateTxt(value: string | undefined | null) {
283    this._avgRateTxt = value;
284  }
285
286  get funcExpand(): boolean {
287    return this.getAttribute('func-expand') === 'true';
288  }
289
290  set funcExpand(b: boolean) {
291    this.setAttribute('func-expand', b ? 'true' : 'false');
292  }
293
294  get sticky(): boolean {
295    return this.hasAttribute('sticky');
296  }
297
298  set sticky(fixed: boolean) {
299    if (fixed) {
300      this.setAttribute('sticky', '');
301    } else {
302      this.removeAttribute('sticky');
303    }
304  }
305
306  get hasParentRowEl(): boolean {
307    return this.parentRowEl !== undefined;
308  }
309
310  get rowDiscard(): boolean {
311    return this.hasAttribute('row-discard');
312  }
313
314  set rowDiscard(value: boolean) {
315    if (value) {
316      this.setAttribute('row-discard', '');
317      this.style.display = 'none';
318    } else {
319      this.removeAttribute('row-discard');
320      this.style.display = 'block';
321    }
322  }
323
324  get collectGroup(): string | undefined {
325    return this._collectGroup;
326  }
327
328  set collectGroup(value: string | undefined) {
329    this._collectGroup = value;
330    this.setAttribute('collect-group', value || '');
331  }
332
333  set rowSetting(value: string) {
334    this.setAttribute('row-setting', value);
335  }
336
337  get rowSetting(): string {
338    return this.getAttribute('row-setting') || 'disable';
339  }
340
341  set rowSettingPopoverDirection(value: string) {
342    if (this.rowSettingPop) {
343      this.rowSettingPop.placement = value;
344    }
345    if (this.rowSettingPop) {
346      this.rowSettingPop.placement = value;
347    }
348  }
349
350  get rowSettingPopoverDirection(): string {
351    return this.rowSettingPop?.placement || 'bottomLeft';
352  }
353
354  set rowSettingList(value: Array<TreeItemData> | null | undefined) {
355    this._rowSettingList = value;
356    if (this.rowSettingTree) {
357      this.rowSettingTree.treeData = value || [];
358    }
359    if (this.rowSettingTree) {
360      this.rowSettingTree.treeData = value || [];
361    }
362  }
363
364  set rowSettingMultiple(value: boolean) {
365    if (this.rowSettingTree) {
366      this.rowSettingTree.multiple = value;
367    }
368  }
369
370  get rowSettingList(): TreeItemData[] | null | undefined {
371    return this._rowSettingList;
372  }
373
374  get collect(): boolean {
375    return this.hasAttribute('collect-type');
376  }
377
378  set collect(value: boolean) {
379    if (value) {
380      this.setAttribute('collect-type', '');
381    } else {
382      this.removeAttribute('collect-type');
383    }
384  }
385
386  get rangeSelect(): boolean {
387    return this._rangeSelect;
388  }
389
390  set rangeSelect(value: boolean) {
391    this._rangeSelect = value;
392  }
393
394  sleeping: boolean = false;
395
396  get rowType(): string | undefined | null {
397    return this.getAttribute('row-type');
398  }
399
400  set rowType(val) {
401    this.setAttribute('row-type', val || '');
402  }
403
404  get rowId(): string | undefined | null {
405    return this.getAttribute('row-id');
406  }
407
408  set rowId(val) {
409    this.setAttribute('row-id', val || '');
410  }
411
412  get rowParentId(): string | undefined | null {
413    return this.getAttribute('row-parent-id');
414  }
415
416  set rowParentId(val) {
417    this.setAttribute('row-parent-id', val || '');
418  }
419
420  get namePrefix(): string | undefined | null {
421    return this.getAttribute('name-prefix');
422  }
423
424  set namePrefix(val) {
425    this.setAttribute('name-prefix', val || '');
426  }
427
428  set rowHidden(val: boolean) {
429    let height = 0;
430    if (val) {
431      this.setAttribute('row-hidden', '');
432      height = 0;
433    } else {
434      this.removeAttribute('row-hidden');
435      height = this.clientHeight;
436    }
437    if (this.collect) {
438      window.publish(window.SmartEvent.UI.RowHeightChange, {
439        expand: this.funcExpand,
440        value: height,
441      });
442    }
443  }
444
445  get name(): string {
446    return this.getAttribute('name') || '';
447  }
448
449  set name(value: string) {
450    this.setAttribute('name', value);
451  }
452
453  get folder(): boolean {
454    return this.hasAttribute('folder');
455  }
456
457  set folder(value: boolean) {
458    if (value) {
459      this.setAttribute('folder', '');
460      this.folderIcon = document.createElement('lit-icon') as LitIcon;
461      this.folderIcon.classList.add('icon');
462      this.folderIcon.setAttribute('name', 'caret-down');
463      this.folderIcon.setAttribute('size', '19');
464      this.folderIcon.style.display = 'flex';
465      this.describeEl?.insertBefore(this.folderIcon, this.describeEl.children[0]);
466    } else {
467      this.removeAttribute('folder');
468    }
469  }
470
471  get expansion(): boolean {
472    return this.hasAttribute('expansion');
473  }
474
475  fragment: DocumentFragment = document.createDocumentFragment();
476
477  set expansion(value) {
478    if (value === this.expansion) {
479      return;
480    }
481    if (value) {
482      this.updateChildRowStatus();
483    } else {
484      this.childRowToFragment(false);
485    }
486    if (value) {
487      this.setAttribute('expansion', '');
488    } else {
489      this.removeAttribute('expansion');
490    }
491    this.dispatchEvent(
492      new CustomEvent('expansion-change', {
493        detail: {
494          expansion: this.expansion,
495          rowType: this.rowType,
496          rowId: this.rowId,
497          rowParentId: this.rowParentId,
498        },
499      })
500    );
501  }
502
503  childRowToFragment(expansion: boolean): void {
504    for (const childrenRow of this.childrenList) {
505      if (!childrenRow.collect) {
506        this.fragment.append(childrenRow);
507      }
508      if (!expansion) {
509        if (childrenRow.childrenList && childrenRow.folder && childrenRow.expansion) {
510          childrenRow.expansion = false;
511        }
512      }
513    }
514  }
515
516  updateChildRowStatus(): void {
517    this.fragment = document.createDocumentFragment();
518    this.childRowToFragment(true);
519    this.insertAfter(this.fragment, this);
520  }
521
522  clearMemory(): void {
523    this.dataList2 = [];
524    this.dataList = [];
525    this.dataListCache = [];
526    this.fixedList = [];
527    if (this.rootEL) {
528      this.rootEL.innerHTML = '';
529    }
530    if (this.folder) {
531      this.childrenList.forEach((child) => {
532        if (child.clearMemory !== undefined) {
533          child.clearMemory();
534        }
535      });
536      this.childrenList = [];
537    }
538  }
539
540  addTemplateTypes(...type: string[]): void {
541    type.forEach((item) => {
542      this.templateType.add(item);
543    });
544    if (this.hasParentRowEl) {
545      this.toParentAddTemplateType(this);
546    }
547  }
548  // @ts-ignore
549  toParentAddTemplateType = (currentRowEl: TraceRow<unknown>): void => {
550    let parentRow = currentRowEl.parentRowEl;
551    if (parentRow !== undefined) {
552      currentRowEl.templateType.forEach((item) => {
553        parentRow!.templateType.add(item);
554      });
555      if (parentRow.parentRowEl !== undefined) {
556        this.toParentAddTemplateType(parentRow);
557      }
558    }
559  };
560
561  //@ts-ignore
562  getHoverStruct(strict: boolean = true, offset: boolean = false, maxKey?: string): T | undefined {
563    if (this.isHover) {
564      if (maxKey) {
565        let arr = this.dataListCache
566          .filter((re) => re.frame && isFrameContainPoint(re.frame, this.hoverX, this.hoverY, strict, offset)) // @ts-ignore
567          .sort((targetA, targetB) => (targetB as unknown)[maxKey] - (targetA as unknown)[maxKey]);
568        return arr[0];
569      } else {
570        return this.dataListCache.find(
571          (re) => re.frame && isFrameContainPoint(re.frame, this.hoverX, this.hoverY, strict, offset)
572        );
573      }
574    }
575  }
576  // @ts-ignore
577  addChildTraceRow(child: TraceRow<unknown>): void {
578    // @ts-ignore
579    TraceRowConfig.allTraceRowList.push(child);
580    child.parentRowEl = this;
581    this.toParentAddTemplateType(child);
582    child.setAttribute('scene', '');
583    this.childrenList.push(child);
584    child.rowHidden = false;
585    this.fragment.appendChild(child);
586  }
587  // @ts-ignore
588  addChildTraceRowAfter(child: TraceRow<unknown>, targetRow: TraceRow<unknown>): void {
589    // @ts-ignore
590    TraceRowConfig.allTraceRowList.push(child);
591    child.parentRowEl = this;
592    this.toParentAddTemplateType(child);
593    let index = this.childrenList.indexOf(targetRow);
594    child.setAttribute('scene', '');
595    if (index !== -1) {
596      this.childrenList.splice(index + 1, 0, child);
597      child.rowHidden = false;
598      this.fragment.insertBefore(child, this.fragment.childNodes.item(index + 1));
599    } else {
600      this.childrenList.push(child);
601      child.rowHidden = false;
602      this.fragment.append(child);
603    }
604  }
605
606  addChildTraceRowBefore(child: TraceRow<BaseStruct>, targetRow: TraceRow<BaseStruct>): void {
607    TraceRowConfig.allTraceRowList.push(child);
608    child.parentRowEl = this;
609    this.toParentAddTemplateType(child);
610    let index = this.childrenList.indexOf(targetRow);
611    child.setAttribute('scene', '');
612    if (index !== -1) {
613      this.childrenList.splice(index, 0, child);
614      this.fragment.insertBefore(child, this.fragment.childNodes.item(index));
615    } else {
616      this.childrenList.push(child);
617      child.rowHidden = false;
618      this.fragment.appendChild(child);
619    }
620  }
621
622  addRowSampleUpload(): void {
623    this.sampleUploadEl = document.createElement('div');
624    this.sampleUploadEl!.className = 'upload';
625    this.sampleUploadEl!.innerHTML = `
626      <input id="file" class="file" accept="application/json"  type="file" style="display:none;pointer-events:none"/>
627      <label for="file" style="cursor:pointer">
628        <lit-icon class="folder" name="copy-csv" size="19"></lit-icon>
629      </label>
630    `;
631    this.jsonFileEl = this.sampleUploadEl!.querySelector('.file') as HTMLInputElement;
632    this.sampleUploadEl!.addEventListener('change', () => {
633      let files = this.jsonFileEl!.files;
634      if (files && files.length > 0) {
635        this.sampleUploadEl!.dispatchEvent(
636          new CustomEvent('sample-file-change', {
637            detail: files[0],
638          })
639        );
640        if (this.jsonFileEl) {
641          this.jsonFileEl.value = '';
642        }
643      }
644    });
645    this.sampleUploadEl!.addEventListener('click', (e): void => {
646      e.stopPropagation();
647    });
648    this.describeEl?.appendChild(this.sampleUploadEl!);
649  }
650  // @ts-ignore
651  addChildTraceRowSpecifyLocation(child: TraceRow<unknown>, index: number): void {
652    // @ts-ignore
653    TraceRowConfig.allTraceRowList.push(child);
654    child.parentRowEl = this;
655    child.setAttribute('scene', '');
656    this.childrenList.splice(index, 0, child);
657    child.rowHidden = false;
658    this.fragment.insertBefore(child, this.fragment.childNodes.item(index));
659  }
660
661  insertAfter(newEl: DocumentFragment, targetEl: HTMLElement): void {
662    let parentEl = targetEl.parentNode;
663    if (parentEl) {
664      if (parentEl!.lastChild === targetEl) {
665        parentEl!.appendChild(newEl);
666      } else {
667        parentEl!.insertBefore(newEl, targetEl.nextSibling);
668      }
669    }
670  }
671
672  sortRenderServiceData(
673    child: TraceRow<BaseStruct>,
674    targetRow: TraceRow<BaseStruct>,
675    threadRowArr: Array<TraceRow<BaseStruct>>,
676    flag: boolean
677  ): void {
678    if (child.rowType === 'thread') {
679      threadRowArr.push(child);
680    } else {
681      let index: number = threadRowArr.indexOf(targetRow);
682      if (index !== -1) {
683        threadRowArr.splice(index + 1, 0, child);
684      } else {
685        threadRowArr.push(child);
686      }
687    }
688    if (flag) {
689      let order: string[] = [
690        'VSyncGenerator',
691        'VSync-rs',
692        'VSync-app',
693        'render_service',
694        'RSUniRenderThre',
695        'Acquire Fence',
696        'RSHardwareThrea',
697        'Present Fence',
698      ];
699      let filterOrderArr: Array<TraceRow<BaseStruct>> = [];
700      let filterNotOrderArr: Array<TraceRow<BaseStruct>> = [];
701      for (let i = 0; i < threadRowArr.length; i++) {
702        // @ts-ignore
703        const element: TraceRow<unknown> = threadRowArr[i];
704        let renderFlag: boolean =
705          element.name.startsWith('render_service') && element.rowId === element.rowParentId ? true : false;
706        if (renderFlag) {
707          // @ts-ignore
708          filterOrderArr.push(element);
709        } else if (order.includes(element.namePrefix!) && !element.name.startsWith('render_service')) {
710          // @ts-ignore
711          filterOrderArr.push(element);
712        } else if (!order.includes(element.namePrefix!) || !renderFlag) {
713          // @ts-ignore
714          filterNotOrderArr.push(element);
715        }
716      }
717      filterOrderArr.sort((star, next) => {
718        return order.indexOf(star.namePrefix!) - order.indexOf(next.namePrefix!);
719      });
720      let combinedArr = [...filterOrderArr, ...filterNotOrderArr];
721      combinedArr.forEach((item): void => {
722        this.addChildTraceRow(item);
723      });
724    }
725  }
726
727  set tip(value: string) {
728    if (this.tipEL) {
729      this.tipEL.innerHTML = value;
730    }
731  }
732
733  get frame(): Rect {
734    if (this._frame) {
735      this._frame.width = TraceRow.FRAME_WIDTH;
736      this._frame.height = this.clientHeight;
737      return this._frame;
738    } else {
739      this._frame = new Rect(0, 0, TraceRow.FRAME_WIDTH, this.clientHeight || 40);
740      return this._frame;
741    }
742  }
743
744  set frame(f: Rect) {
745    this._frame = f;
746  }
747
748  get checkType(): string {
749    return this.getAttribute('check-type') || '';
750  }
751
752  set checkType(value: string) {
753    if (!value || value.length === 0) {
754      this.removeAttribute('check-type');
755      return;
756    }
757    if (this.getAttribute('check-type') === value) {
758      return;
759    }
760    if (this.folder) {
761      this.childrenList.forEach((it) => (it.checkType = value));
762    }
763    this.setAttribute('check-type', value);
764    if (this.hasAttribute('disabled-check')) {
765      this.checkBoxEL!.style.display = 'none';
766      return;
767    }
768    switch (value) {
769      case '-1':
770        this.checkBoxEL!.style.display = 'none';
771        this.rangeSelect = false;
772        break;
773      case '0':
774        this.checkBoxEL!.style.display = 'flex';
775        this.checkBoxEL!.checked = false;
776        this.checkBoxEL!.indeterminate = false;
777        this.rangeSelect = false;
778        break;
779      case '1':
780        this.checkBoxEL!.style.display = 'flex';
781        this.checkBoxEL!.checked = false;
782        this.checkBoxEL!.indeterminate = true;
783        this.rangeSelect = false;
784        break;
785      case '2':
786        this.rangeSelect = true;
787        this.checkBoxEL!.style.display = 'flex';
788        this.checkBoxEL!.checked = true;
789        this.checkBoxEL!.indeterminate = false;
790        break;
791    }
792  }
793
794  get drawType(): number {
795    return this._drawType;
796  }
797
798  set drawType(value: number) {
799    this._drawType = value; // @ts-ignore
800    let radioList: NodeListOf<unknown> = this.shadowRoot!.querySelectorAll('input[type=radio][name=status]');
801    if (radioList!.length > 0) {
802      // @ts-ignore
803      radioList[Number(value)].checked = true;
804    }
805  }
806
807  get highlight(): boolean {
808    return this.hasAttribute('expansion');
809  }
810
811  set highlight(value: boolean) {
812    if (value) {
813      this.setAttribute('highlight', '');
814    } else {
815      this.removeAttribute('highlight');
816    }
817  }
818
819  set folderPaddingLeft(value: number) {
820    if (this.folderIcon) {
821      this.folderIcon.style.marginLeft = `${value}px`;
822    }
823  }
824
825  set folderTextLeft(value: number) {
826    this.nameEL!.style.marginLeft = `${value}px`;
827  }
828
829  initElements(): void {
830    this.rootEL = this.shadowRoot?.querySelector('.root');
831    this.checkBoxEL = this.shadowRoot?.querySelector<LitCheckBox>('.lit-check-box');
832    this.collectEL = this.shadowRoot?.querySelector<LitIcon>('.collect');
833    this.describeEl = this.shadowRoot?.querySelector('.describe');
834    this.nameEL = this.shadowRoot?.querySelector('.name');
835    this.canvasVessel = this.shadowRoot?.querySelector('.panel-vessel');
836    this.tipEL = this.shadowRoot?.querySelector('.tip'); // @ts-ignore
837    let canvasNumber = this.args.canvasNumber; // @ts-ignore
838    if (!this.args.skeleton) {
839      for (let i = 0; i < canvasNumber; i++) {
840        let canvas = document.createElement('canvas');
841        canvas.className = 'panel';
842        this.canvas.push(canvas);
843        if (this.canvasVessel) {
844          this.canvasVessel.appendChild(canvas);
845        }
846      }
847    }
848    this.checkBoxEvent();
849    this.describeEl?.addEventListener('click', () => {
850      if (this.folder) {
851        this.expansion = !this.expansion;
852        this.sticky = this.expansion;
853      }
854    });
855    this.funcExpand = true;
856    if (this.rowSettingTree) {
857      this.rowSettingTree.onChange = (e: unknown): void => {
858        // @ts-ignore
859        this.rowSettingPop!.visible = false;
860        if (this.rowSettingTree?.multiple) {
861          // @ts-ignore
862          this.rowSettingPop!.visible = true;
863        } else {
864          // @ts-ignore
865          this.rowSettingPop!.visible = false;
866        } //@ts-ignore
867        this.onRowSettingChangeHandler?.(this.rowSettingTree!.getCheckdKeys(), this.rowSettingTree!.getCheckdNodes());
868      };
869    }
870    this.checkType = '-1';
871  }
872
873  private checkBoxEvent(): void {
874    this.checkBoxEL!.onchange = (ev: unknown): void => {
875      info('checkBoxEL onchange '); // @ts-ignore
876      if (!ev.target.checked) {
877        info('checkBoxEL target not checked');
878        this.rangeSelect = false;
879        this.checkType = '0';
880      } else {
881        this.rangeSelect = true;
882        this.checkType = '2';
883      } // @ts-ignore
884      this.setCheckBox(ev.target.checked); // @ts-ignore
885      ev.stopPropagation();
886    };
887    // 防止事件冒泡触发两次describeEl的点击事件
888    this.checkBoxEL!.onclick = (ev: unknown): void => {
889      // @ts-ignore
890      ev.stopPropagation();
891    };
892  }
893
894  addRowCheckFilePop(): void {
895    this.rowCheckFilePop = document.createElement('litpopover') as LitPopover;
896    this.rowCheckFilePop.innerHTML = `<div slot="content" id="jsonFile" style="display: block;height: auto;max-height:200px;overflow-y:auto">
897    </div>
898    <lit-icon name="copy-csv" size="19" id="myfolder"></lit-icon>
899    <input type="file" id="jsoninput" style="width:0px;height:0px"placeholder=''/>`;
900    this.rowCheckFilePop.id = 'rowCheckFile';
901    this.rowCheckFilePop.className = 'popover checkFile';
902    this.rowCheckFilePop.setAttribute('trigger', 'click');
903    this.rowCheckFilePop?.addEventListener('mouseenter', (e): void => {
904      window.publish(window.SmartEvent.UI.HoverNull, undefined);
905    });
906    this.fileEL = this.rowCheckFilePop.querySelector('#jsoninput');
907    this.rowCheckFilePop.addEventListener('click', (e): void => {
908      // @ts-ignore
909      this.fileEL.click();
910    }); // @ts-ignore
911    this.fileEL.addEventListener('click', (event: Event) => {
912      event.stopPropagation();
913    });
914
915    window.addEventListener('storage', (e): void => {
916      if (e.storageArea === sessionStorage) {
917        if (e.key === 'freqInfoData') {
918          this.onRowCheckFileChangeHandler?.();
919        }
920      }
921    }); // @ts-ignore
922    this.fileEL.addEventListener(
923      'change',
924      (e: unknown): void => {
925        // @ts-ignore
926        let file = e.target.files[0];
927        if (file && file.type === 'application/json') {
928          let file_reader = new FileReader();
929          file_reader.readAsText(file, 'UTF-8');
930          file_reader.onload = (): void => {
931            let fc = file_reader.result;
932            window.sessionStorage.setItem('freqInfoData', JSON.stringify(fc));
933            this.onRowCheckFileChangeHandler?.();
934            alert('json文件上传成功!'); // @ts-ignore
935            this.fileEL.value = '';
936          };
937        } else {
938          return;
939        }
940      },
941      false
942    );
943    this.describeEl?.appendChild(this.rowCheckFilePop);
944  }
945
946  addRowSettingPop(): void {
947    this.rowSettingPop = document.createElement('lit-popover') as LitPopover;
948    this.rowSettingPop.innerHTML = `<div slot="content" id="settingList" style="display: block;height: auto;max-height:200px;overflow-y:auto">
949      <lit-tree id="rowSettingTree" checkable="true"></lit-tree>
950      </div>
951      <lit-icon name="setting" size="19" id="setting"></lit-icon>`;
952    this.rowSettingPop.id = 'rowSetting';
953    this.rowSettingPop.className = 'popover setting';
954    this.rowSettingPop.setAttribute('placement', 'bottomLeft');
955    this.rowSettingPop.setAttribute('trigger', 'click');
956    this.rowSettingPop.setAttribute('haveRadio', 'true');
957    this.rowSettingTree = this.rowSettingPop.querySelector('#rowSettingTree') as LitTree;
958    this.rowSettingTree.onChange = (): void => {
959      let isVisible = false;
960      // @ts-ignore
961      this.rowSettingPop!.visible = isVisible;
962      if (this.rowSettingTree?.multiple) {
963        isVisible = true;
964      }
965      // @ts-ignore
966      this.rowSettingPop!.visible = isVisible; //@ts-ignore
967      this.onRowSettingChangeHandler?.(this.rowSettingTree!.getCheckdKeys(), this.rowSettingTree!.getCheckdNodes());
968    };
969    this.rowSettingPop?.addEventListener('mouseenter', (): void => {
970      window.publish(window.SmartEvent.UI.HoverNull, undefined);
971    });
972    this.describeEl?.appendChild(this.rowSettingPop);
973  }
974
975  getRowSettingKeys(): Array<string> {
976    if (this.rowSetting === 'enable') {
977      //@ts-ignore
978      return this.rowSettingTree!.getCheckdKeys();
979    }
980    return [];
981  }
982
983  expandFunc(): void {
984    if (this._enableCollapseChart && !this.funcExpand) {
985      this.style.height = `${this.funcMaxHeight}px`;
986      this.funcExpand = true;
987      if (this.collect) {
988        window.publish(window.SmartEvent.UI.RowHeightChange, {
989          expand: this.funcExpand,
990          value: this.funcMaxHeight - 20,
991        });
992      }
993    }
994  }
995
996  enableCollapseChart(): void {
997    this._enableCollapseChart = true;
998    this.nameEL!.onclick = (): void => {
999      if (this.funcMaxHeight > 20 || this.clientHeight > 20) {
1000        if (this.funcExpand) {
1001          this.funcMaxHeight = this.clientHeight;
1002          this.style.height = '20px';
1003          this.funcExpand = false;
1004        } else {
1005          this.style.height = `${this.funcMaxHeight}px`;
1006          this.funcExpand = true;
1007        }
1008        TraceRow.range!.refresh = true;
1009        this.needRefresh = true;
1010        this.draw(false);
1011        if (this.collect) {
1012          window.publish(window.SmartEvent.UI.RowHeightChange, {
1013            expand: this.funcExpand,
1014            value: this.funcMaxHeight - 20,
1015          });
1016        }
1017      }
1018    };
1019  }
1020
1021  initCanvas(list: Array<HTMLCanvasElement>): void {
1022    let timerShaftEL = document!
1023      .querySelector('body > sp-application')!
1024      .shadowRoot!.querySelector('#sp-system-trace')!
1025      .shadowRoot!.querySelector('div > timer-shaft-element');
1026    let timerShaftCanvas = timerShaftEL!.shadowRoot!.querySelector<HTMLCanvasElement>('canvas');
1027    let tempHeight: number = 0;
1028    if (this.rowType === TraceRow.ROW_TYPE_FUNC) {
1029      tempHeight = 20;
1030    } else if (this.rowType === TraceRow.ROW_TYPE_THREAD) {
1031      tempHeight = 30;
1032    } else if (this.rowType === TraceRow.ROW_TYPE_SYSTEM_ENERGY) {
1033      tempHeight = 80;
1034    } else if (this.rowType === TraceRow.ROW_TYPE_POWER_ENERGY) {
1035      tempHeight = 200;
1036    } else if (this.rowType === TraceRow.ROW_TYPE_ANOMALY_ENERGY) {
1037      tempHeight = 55;
1038    } else {
1039      tempHeight = 40;
1040    }
1041    this.dpr = window.devicePixelRatio || 1;
1042    list.forEach((canvas): void => {
1043      this.rootEL!.style.height = `${this.getAttribute('height') || '40'}px`;
1044      canvas.style.width = timerShaftCanvas!.style.width;
1045      canvas.style.height = `${tempHeight}px`;
1046      this.canvasWidth = timerShaftCanvas!.width;
1047      this.canvasHeight = Math.ceil(tempHeight * this.dpr);
1048      canvas.width = this.canvasWidth;
1049      canvas.height = this.canvasHeight;
1050      // @ts-ignore
1051      this.offscreen.push(canvas!.transferControlToOffscreen());
1052    });
1053  }
1054
1055  updateWidth(width: number): void {
1056    this.dpr = window.devicePixelRatio || 1;
1057    let tempHeight: number = 0;
1058    if (this.rowType === TraceRow.ROW_TYPE_FUNC) {
1059      tempHeight = 20;
1060    } else if (this.rowType === TraceRow.ROW_TYPE_THREAD) {
1061      tempHeight = 30;
1062    } else if (this.rowType === TraceRow.ROW_TYPE_SYSTEM_ENERGY) {
1063      tempHeight = 90;
1064    } else if (this.rowType === TraceRow.ROW_TYPE_POWER_ENERGY) {
1065      tempHeight = 200;
1066    } else if (this.rowType === TraceRow.ROW_TYPE_ANOMALY_ENERGY) {
1067      tempHeight = 55;
1068    } else {
1069      tempHeight = 40;
1070    }
1071    if (this.canvas.length > 1) {
1072      tempHeight = 20;
1073    }
1074    this.canvas.forEach((it): void => {
1075      this.canvasWidth = Math.ceil((width - (this.describeEl?.clientWidth || 248)) * this.dpr);
1076      this.canvasHeight = Math.ceil(tempHeight * this.dpr);
1077      it!.style.width = `${width - (this.describeEl?.clientWidth || 248)}px`; // @ts-ignore
1078      if (this.args.isOffScreen) {
1079        this.draw(true);
1080      }
1081    });
1082  }
1083
1084  drawLine(item: HTMLDivElement, direction: string /*string[top|bottom]*/): void {
1085    if (!item) {
1086      return;
1087    }
1088    switch (direction) {
1089      case 'top':
1090        item.classList.remove('line-bottom');
1091        item.classList.add('line-top');
1092        break;
1093      case 'bottom':
1094        item.classList.remove('line-top');
1095        item.classList.add('line-bottom');
1096        break;
1097      case '':
1098        item.classList.remove('line-top');
1099        item.classList.remove('line-bottom');
1100        break;
1101    }
1102  }
1103
1104  connectedCallback(): void {
1105    this.describeEl!.ondragstart = (ev: DragEvent): void => this.rowDragstart(ev);
1106    this.describeEl!.ondragleave = (ev: unknown): void => {
1107      // @ts-ignore
1108      this.drawLine(ev.currentTarget, '');
1109      return undefined;
1110    };
1111    this.describeElEvent();
1112    this.collectEL!.onclick = (e): void => {
1113      this.collect = !this.collect;
1114      if (this.collect) {
1115        this.describeEl!.draggable = false;
1116      } else {
1117        this.describeEl!.draggable = false;
1118      }
1119      document.dispatchEvent(
1120        new CustomEvent('collect', {
1121          detail: {
1122            type: e.type,
1123            row: this,
1124          },
1125        })
1126      );
1127      this.favoriteChangeHandler?.(this);
1128    }; // @ts-ignore
1129    if (!this.args.skeleton) {
1130      this.initCanvas(this.canvas);
1131    }
1132  }
1133
1134  private describeElEvent(): void {
1135    this.describeEl!.ondragend = (ev: unknown): void => {
1136      rowDragId = null; // @ts-ignore
1137      ev.target.classList.remove('drag'); // @ts-ignore
1138      this.drawLine(ev.currentTarget, '');
1139      return undefined;
1140    };
1141    this.describeEl!.ondragover = (ev: unknown): undefined => {
1142      if (!this.collect || rowDragId === this.rowId) {
1143        return;
1144      } // @ts-ignore
1145      let rect = ev.currentTarget.getBoundingClientRect(); // @ts-ignore
1146      if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) {
1147        //上面
1148        dragDirection = 'top'; // @ts-ignore
1149        this.drawLine(ev.currentTarget, 'top'); // @ts-ignore
1150      } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) {
1151        //下面
1152        dragDirection = 'bottom'; // @ts-ignore
1153        this.drawLine(ev.currentTarget, 'bottom');
1154      }
1155      return undefined;
1156    };
1157    this.describeEl!.ondrop = (ev: unknown): void => {
1158      if (!this.collect) {
1159        return;
1160      } // @ts-ignore
1161      this.drawLine(ev.currentTarget, '');
1162      let spacer = this.parentElement!.previousElementSibling! as HTMLDivElement;
1163      let startDragNode = collectList.findIndex((it): boolean => it.rowId === rowDragId);
1164      let endDragNode = collectList.findIndex((it): boolean => it === this);
1165      if (startDragNode === -1 || endDragNode === -1) {
1166        return;
1167      }
1168      if (startDragNode < endDragNode && dragDirection === 'top') {
1169        endDragNode--;
1170      } else if (startDragNode > endDragNode && dragDirection === 'bottom') {
1171        endDragNode++;
1172      }
1173      collectList.splice(endDragNode, 0, ...collectList.splice(startDragNode, 1));
1174      collectList.forEach((it, i): void => {
1175        if (i === 0) {
1176          // @ts-ignore
1177          it.style.top = `${spacer.offsetTop + 48}px`;
1178        } else {
1179          it.style.top = `${collectList[i - 1].offsetTop + collectList[i - 1].offsetHeight}px`;
1180        }
1181      });
1182    };
1183  }
1184
1185  rowDragstart(ev: unknown): void {
1186    rowDragId = this.rowId; // @ts-ignore
1187    ev.target.classList.add('drag');
1188  }
1189
1190  setCheckBox(isCheck: boolean): void {
1191    if (this.folder) {
1192      // favorite row  check change;
1193      window.publish(window.SmartEvent.UI.CheckALL, {
1194        rowId: this.rowId,
1195        isCheck: isCheck,
1196      });
1197      this.childrenList!.forEach((ck): void => {
1198        ck.setAttribute('check-type', isCheck ? '2' : '0');
1199        let allCheck: LitCheckBox | null | undefined = ck?.shadowRoot?.querySelector('.lit-check-box');
1200        if (allCheck) {
1201          allCheck!.checked = isCheck;
1202        }
1203      });
1204    }
1205    this.selectChangeHandler?.(this);
1206  }
1207
1208  onMouseHover(x: number, y: number, tip: boolean = true): T | undefined | null {
1209    if (this.tipEL) {
1210      this.tipEL.style.display = 'none';
1211    }
1212    return null;
1213  }
1214
1215  setTipLeft(x: number, struct: unknown): void {
1216    if (struct === null && this.tipEL) {
1217      this.tipEL.style.display = 'none';
1218      return;
1219    }
1220    if (this.tipEL) {
1221      this.tipEL.style.display = 'flex';
1222      if (x + this.tipEL.clientWidth > (this.canvasVessel!.clientWidth || 0)) {
1223        this.tipEL.style.transform = `translateX(${x - this.tipEL.clientWidth - 1}px)`;
1224      } else {
1225        this.tipEL.style.transform = `translateX(${x}px)`;
1226      }
1227    }
1228  }
1229
1230  onMouseLeave(x: number, y: number): void {
1231    if (this.tipEL) {
1232      this.tipEL.style.display = 'none';
1233    }
1234  }
1235
1236  loadingPin1: number = 0;
1237  loadingPin2: number = 0;
1238  static currentActiveRows: Array<string> = [];
1239
1240  drawFrame(): void {
1241    if (!this.hasAttribute('row-hidden')) {
1242      if (!this.loadingFrame || window.isLastFrame || !this.isComplete) {
1243        if (this.needRefresh || window.isLastFrame) {
1244          this.loadingFrame = true;
1245          this.needRefresh = false;
1246          this.loadingPin1 = TraceRow.range?.startNS || 0;
1247          this.loadingPin2 = TraceRow.range?.endNS || 0;
1248          TraceRow.currentActiveRows.push(`${this.rowType}-${this.rowId}`);
1249          this.supplierFrame!().then((res) => {
1250            if (this.onComplete) {
1251              this.onComplete();
1252              this.onComplete = undefined;
1253            }
1254            this.dataListCache = res;
1255            this.dataListCache.push(...this.fixedList);
1256            this.isComplete = true;
1257            this.loadingFrame = false;
1258            let idx = TraceRow.currentActiveRows.findIndex((it): boolean => it === `${this.rowType}-${this.rowId}`);
1259            if (idx !== -1) {
1260              TraceRow.currentActiveRows.splice(idx, 1);
1261            }
1262            requestAnimationFrame(() => {
1263              this.onThreadHandler?.(true, null);
1264              if (TraceRow.currentActiveRows) {
1265                window.publish(window.SmartEvent.UI.LoadFinish, '');
1266              }
1267              window.publish(window.SmartEvent.UI.LoadFinishFrame, '');
1268            });
1269          });
1270        } else if (this.fixedList.length > 0 && !this.dataListCache.includes(this.fixedList[0])) {
1271          this.dataListCache.push(this.fixedList[0]);
1272        }
1273      }
1274      this.onThreadHandler?.(true, null);
1275    }
1276  }
1277
1278  draw(useCache: boolean = false): void {
1279    this.dpr = window.devicePixelRatio || 1;
1280    if (this.sleeping) {
1281      return;
1282    }
1283    if (this.supplierFrame) {
1284      //如果设置了实时渲染,则调用drawFrame
1285      this.drawFrame();
1286      return;
1287    }
1288    if (this.online) {
1289      if (!useCache && !TraceRow.isUserInteraction) {
1290        this.supplier?.().then((res) => {
1291          // @ts-ignore
1292          this.onThreadHandler?.(useCache, res as unknown);
1293        });
1294      }
1295      this.onThreadHandler?.(useCache, null);
1296      return;
1297    }
1298    if (!this.isComplete) {
1299      if (this.supplier && !this.isLoading) {
1300        this.isLoading = true;
1301        this.must = true;
1302        let promise = this.supplier();
1303        if (promise) {
1304          promise.then((res): void => {
1305            this.dataList = res;
1306            if (this.onComplete) {
1307              this.onComplete();
1308            }
1309            window.publish(window.SmartEvent.UI.TraceRowComplete, this);
1310            this.isComplete = true;
1311            this.isLoading = false;
1312            this.draw(false);
1313          });
1314        } else {
1315          this.isLoading = false;
1316          this.draw(false);
1317        }
1318      }
1319    } else {
1320      if (!this.hasAttribute('row-hidden')) {
1321        if (this.onThreadHandler && this.dataList) {
1322          this.onThreadHandler!(false, null);
1323        }
1324      }
1325    }
1326  }
1327
1328  canvasSave(ctx: CanvasRenderingContext2D): void {
1329    ctx.save();
1330    ctx.translate(0, this.translateY);
1331    const clipRect = new Path2D(); // @ts-ignore
1332    clipRect.rect(0, 0, this.frame.width, this.frame.height);
1333    ctx.clip(clipRect);
1334  }
1335
1336  canvasRestore(ctx: CanvasRenderingContext2D, trace?: SpSystemTrace | null): void {
1337    drawSelectionRange(ctx, this);
1338    ctx.restore();
1339  }
1340
1341  clearCanvas(ctx: CanvasRenderingContext2D): void {
1342    if (ctx) {
1343      this.canvas.forEach((it): void => {
1344        ctx.clearRect(0, 0, it!.clientWidth || 0, it!.clientHeight || 0);
1345      });
1346    }
1347  }
1348
1349  drawLines(ctx: CanvasRenderingContext2D): void {
1350    if (ctx) {
1351      ctx.lineWidth = 1;
1352      ctx.strokeStyle = this.getLineColor();
1353      TraceRow.range?.xs.forEach((it): void => {
1354        ctx.moveTo(Math.floor(it), 0);
1355        ctx.lineTo(Math.floor(it), this.shadowRoot?.host.clientHeight || 0);
1356      });
1357      ctx.stroke();
1358    }
1359  }
1360
1361  getLineColor(): string {
1362    return window.getComputedStyle(this.rootEL!, null).getPropertyValue('border-bottom-color');
1363  }
1364
1365  drawSelection(ctx: CanvasRenderingContext2D): void {
1366    if (this.rangeSelect) {
1367      TraceRow.rangeSelectObject!.startX = Math.floor(
1368        ns2x(
1369          TraceRow.rangeSelectObject!.startNS!,
1370          TraceRow.range!.startNS,
1371          TraceRow.range!.endNS,
1372          TraceRow.range!.totalNS!, // @ts-ignore
1373          this.frame
1374        )
1375      );
1376      TraceRow.rangeSelectObject!.endX = Math.floor(
1377        ns2x(
1378          TraceRow.rangeSelectObject!.endNS!,
1379          TraceRow.range!.startNS,
1380          TraceRow.range!.endNS,
1381          TraceRow.range!.totalNS!, // @ts-ignore
1382          this.frame
1383        )
1384      );
1385      if (ctx) {
1386        ctx.globalAlpha = 0.5;
1387        ctx.fillStyle = '#666666';
1388        ctx.fillRect(
1389          TraceRow.rangeSelectObject!.startX!, // @ts-ignore
1390          this.frame.y,
1391          TraceRow.rangeSelectObject!.endX! - TraceRow.rangeSelectObject!.startX!, // @ts-ignore
1392          this.frame.height
1393        );
1394        ctx.globalAlpha = 1;
1395      }
1396    }
1397  }
1398
1399  isInTimeRange(startTime: number, duration: number): boolean {
1400    return (
1401      (startTime || 0) + (duration || 0) > (TraceRow.range?.startNS || 0) &&
1402      (startTime || 0) < (TraceRow.range?.endNS || 0)
1403    );
1404  }
1405
1406  buildArgs(obj: unknown): unknown {
1407    let result: unknown = {
1408      list: this.must ? this.dataList : undefined,
1409      offscreen: !this.isTransferCanvas ? this.offscreen[0] : undefined, //是否离屏
1410      dpr: this.dpr, //屏幕dpr值
1411      xs: TraceRow.range?.xs, //线条坐标信息
1412      isHover: this.isHover,
1413      hoverX: this.hoverX,
1414      hoverY: this.hoverY,
1415      canvasWidth: this.canvasWidth,
1416      canvasHeight: this.canvasHeight,
1417      isRangeSelect: this.rangeSelect,
1418      rangeSelectObject: TraceRow.rangeSelectObject,
1419      lineColor: this.getLineColor(),
1420      chartColor: ColorUtils.MD_PALETTE[0],
1421      startNS: TraceRow.range?.startNS || 0,
1422      endNS: TraceRow.range?.endNS || 0,
1423      totalNS: TraceRow.range?.totalNS || 0,
1424      slicesTime: TraceRow.range?.slicesTime,
1425      range: TraceRow.range,
1426      frame: this.frame,
1427      flagMoveInfo: null,
1428      flagSelectedInfo: null,
1429      wakeupBean: null,
1430    }; // @ts-ignore
1431    Reflect.ownKeys(obj).forEach((it): void => {
1432      // @ts-ignore
1433      result[it] = obj[it];
1434    });
1435    return result;
1436  }
1437
1438  getTransferArray(): unknown[] {
1439    let tsf = [];
1440    if (!this.isTransferCanvas) {
1441      tsf.push(this.offscreen[0]);
1442    }
1443    if (this.must && this.dataList instanceof ArrayBuffer) {
1444      tsf.push(this.dataList);
1445    }
1446    return tsf;
1447  }
1448
1449  attributeChangedCallback(name: string, oldValue: string, newValue: string): void {
1450    switch (name) {
1451      case 'name':
1452        if (this.nameEL) {
1453          this.nameEL.textContent = newValue;
1454          this.nameEL.title = newValue;
1455        }
1456        break;
1457      case 'height':
1458        if (newValue !== oldValue) {
1459          // @ts-ignore
1460          if (!this.args.isOffScreen) {
1461          }
1462        }
1463        break;
1464      case 'check-type':
1465        if (newValue === 'check') {
1466          this.checkBoxEL?.setAttribute('checked', '');
1467        } else {
1468          this.checkBoxEL?.removeAttribute('checked');
1469        }
1470        break;
1471    }
1472  }
1473
1474  focusContain(e: MouseEvent, inFavoriteArea: boolean): boolean {
1475    let _y = (e.currentTarget as HTMLElement).getBoundingClientRect().y;
1476    let myRect = this.getBoundingClientRect();
1477    let x = e.offsetX;
1478    let y = e.offsetY + _y;
1479    if (x >= myRect.x && x <= myRect.x + myRect.width && y >= myRect.y && y <= myRect.y + myRect.height) {
1480      this.hoverX = x - this.describeEl!.clientWidth;
1481      this.hoverY = y - myRect.y;
1482      this.isHover = this.collect === inFavoriteArea;
1483      return true;
1484    } else {
1485      this.isHover = false;
1486      if (this.tipEL) {
1487        this.tipEL.style.display = 'none';
1488      }
1489      return false;
1490    }
1491  }
1492
1493  initHtml(): string {
1494    return TraceRowHtml;
1495  }
1496}
1497