• 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<any> = [];
44let rowDragElement: EventTarget | undefined | null;
45let dragDirection: string = '';
46
47@element('trace-row')
48export class TraceRow<T extends BaseStruct> extends HTMLElement {
49  sharedArrayBuffers: any;
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_ALL_APPSTARTUPS = 'all-appstartups';
130  static FRAME_WIDTH: number = 0;
131  static range: TimeRange | undefined | null;
132  static rangeSelectObject: RangeSelectStruct | undefined;
133  static ROW_TYPE_HI_SYSEVENT = 'hi-sysevent';
134  public obj: TraceRowObject<any> | undefined | null;
135  isHover: boolean = false;
136  hoverX: number = 0;
137  hoverY: number = 0;
138  index: number = 0;
139  public must: boolean = false;
140  public isTransferCanvas = false;
141  onComplete: Function | undefined;
142  isComplete: boolean = false;
143  public dataList: Array<T> = [];
144  public dataList2: Array<T> = [];
145  public dataListCache: Array<T> = [];
146  public fixedList: Array<T> = [];
147  public sliceCache: number[] = [-1, -1];
148  public describeEl: HTMLElement | null | undefined;
149  public canvas: Array<HTMLCanvasElement> = [];
150  public canvasVessel: HTMLDivElement | null | undefined;
151  public tipEL: HTMLDivElement | null | undefined;
152  public checkBoxEL: LitCheckBox | null | undefined;
153  public collectEL: LitIcon | null | undefined;
154  public onThreadHandler: ((useCache: boolean, buf: ArrayBuffer | undefined | null) => void) | undefined | null;
155  public onRowSettingChangeHandler: ((keys: Array<string>, nodes: Array<any>) => void) | undefined | null;
156  public onRowCheckFileChangeHandler: ((file: string | ArrayBuffer | null) => void) | undefined | null;
157  public supplier: (() => Promise<Array<T>>) | undefined | null;
158  public favoriteChangeHandler: ((fav: TraceRow<any>) => void) | undefined | null;
159  public selectChangeHandler: ((traceRow: TraceRow<any>) => void) | undefined | null;
160  dpr = window.devicePixelRatio || 1;
161  // @ts-ignore
162  offscreen: Array<OffscreenCanvas | undefined> = [];
163  canvasWidth = 0;
164  canvasHeight = 0;
165  private _collectGroup: string | undefined;
166  public _frame: Rect | undefined;
167  public isLoading: boolean = false;
168  public tampName: string = '';
169  public readonly args: any;
170  public templateType: Set<string> = new Set<string>();
171  private rootEL: HTMLDivElement | null | undefined;
172  private nameEL: HTMLLabelElement | null | undefined;
173  private rowSettingTree: LitTree | null | undefined;
174  private rowSettingPop: LitPopover | null | undefined;
175  private fileEL: any;
176  private rowCheckFilePop: LitPopover | null | undefined;
177  private _rangeSelect: boolean = false;
178  private _drawType: number = 0;
179  private _enableCollapseChart: boolean = false;
180  online: boolean = false;
181  static isUserInteraction: boolean;
182  asyncFuncName: string | undefined | null;
183  asyncFuncNamePID: number | undefined | null;
184  translateY: number = 0; //single canvas offsetY;
185  childrenList: Array<TraceRow<any>> = [];
186  parentRowEl: TraceRow<any> | undefined;
187  _rowSettingList: Array<TreeItemData> | null | undefined;
188  public supplierFrame: (() => Promise<Array<T>>) | undefined | null; //实时查询
189  public getCacheData: ((arg: any) => Promise<Array<any>> | undefined) | undefined; //实时查询
190  public loadingFrame: boolean = false; //实时查询,正在查询中
191  public needRefresh: boolean = true;
192  _docompositionList: Array<number> | undefined;
193  public folderIcon: LitIcon | null | undefined;
194
195  focusHandler?: (ev: MouseEvent) => void | undefined;
196  findHoverStruct?: () => void | undefined;
197  public funcMaxHeight: number = 0;
198  currentContext: CanvasRenderingContext2D | undefined | null;
199
200  constructor(
201    args: {
202      canvasNumber: number;
203      alpha: boolean;
204      contextId: string;
205      isOffScreen: boolean;
206      skeleton?: boolean;
207    } = {
208      canvasNumber: 1,
209      alpha: false,
210      contextId: '2d',
211      isOffScreen: true,
212      skeleton: false,
213    }
214  ) {
215    super();
216    this.args = args;
217    this.attachShadow({ mode: 'open' }).innerHTML = this.initHtml();
218    this.initElements();
219  }
220
221  static skeleton<T extends BaseStruct>(): TraceRow<T> {
222    let tr = new TraceRow<T>({
223      alpha: false,
224      canvasNumber: 0,
225      contextId: '',
226      isOffScreen: false,
227      skeleton: true,
228    });
229    tr.isTransferCanvas = true;
230    return tr;
231  }
232
233  static get observedAttributes() {
234    return [
235      'folder',
236      'sticky',
237      'name',
238      'expansion',
239      'children',
240      'height',
241      'row-type',
242      'row-id',
243      'row-parent-id',
244      'sleeping',
245      'check-type',
246      'collect-type',
247      'collect-group',
248      'disabled-check',
249      'row-discard',
250      'func-expand',
251      'row-setting',
252      'row-setting-list',
253      'row-setting-popover-direction',
254    ];
255  }
256  get docompositionList(): Array<number> | undefined {
257    return this._docompositionList;
258  }
259
260  set docompositionList(value: Array<number> | undefined) {
261    this._docompositionList = value;
262  }
263
264  get funcExpand(): boolean {
265    return this.getAttribute('func-expand') === 'true';
266  }
267
268  set funcExpand(b: boolean) {
269    this.setAttribute('func-expand', b ? 'true' : 'false');
270  }
271  get sticky(): boolean {
272    return this.hasAttribute('sticky');
273  }
274  set sticky(fixed: boolean) {
275    if (fixed) {
276      this.setAttribute('sticky', '');
277    } else {
278      this.removeAttribute('sticky');
279    }
280  }
281  get hasParentRowEl(): boolean {
282    return this.parentRowEl !== undefined;
283  }
284
285  get rowDiscard(): boolean {
286    return this.hasAttribute('row-discard');
287  }
288
289  set rowDiscard(value: boolean) {
290    if (value) {
291      this.setAttribute('row-discard', '');
292      this.style.display = 'none';
293    } else {
294      this.removeAttribute('row-discard');
295      this.style.display = 'block';
296    }
297  }
298
299  get collectGroup(): string | undefined {
300    return this._collectGroup;
301  }
302
303  set collectGroup(value: string | undefined) {
304    this._collectGroup = value;
305    this.setAttribute('collect-group', value || '');
306  }
307
308  set rowSetting(value: string) {
309    this.setAttribute('row-setting', value);
310  }
311
312  get rowSetting(): string {
313    return this.getAttribute('row-setting') || 'disable';
314  }
315
316  set rowSettingPopoverDirection(value: string) {
317    if (this.rowSettingPop) {
318      this.rowSettingPop.placement = value;
319    }
320    if (this.rowSettingPop) {
321      this.rowSettingPop.placement = value;
322    }
323  }
324
325  get rowSettingPopoverDirection(): string {
326    return this.rowSettingPop?.placement || 'bottomLeft';
327  }
328
329  set rowSettingList(value: Array<TreeItemData> | null | undefined) {
330    this._rowSettingList = value;
331    if (this.rowSettingTree) {
332      this.rowSettingTree.treeData = value || [];
333    }
334    if (this.rowSettingTree) {
335      this.rowSettingTree.treeData = value || [];
336    }
337  }
338
339  set rowSettingMultiple(value: boolean) {
340    if (this.rowSettingTree) {
341      this.rowSettingTree.multiple = value;
342    }
343  }
344
345  get rowSettingList(): TreeItemData[] | null | undefined {
346    return this._rowSettingList;
347  }
348
349  get collect(): boolean {
350    return this.hasAttribute('collect-type');
351  }
352
353  set collect(value) {
354    if (value) {
355      this.setAttribute('collect-type', '');
356    } else {
357      this.removeAttribute('collect-type');
358    }
359  }
360
361  get rangeSelect(): boolean {
362    return this._rangeSelect;
363  }
364
365  set rangeSelect(value: boolean) {
366    this._rangeSelect = value;
367  }
368
369  sleeping: boolean = false;
370
371  get rowType(): string | undefined | null {
372    return this.getAttribute('row-type');
373  }
374
375  set rowType(val) {
376    this.setAttribute('row-type', val || '');
377  }
378
379  get rowId(): string | undefined | null {
380    return this.getAttribute('row-id');
381  }
382
383  set rowId(val) {
384    this.setAttribute('row-id', val || '');
385  }
386
387  get rowParentId(): string | undefined | null {
388    return this.getAttribute('row-parent-id');
389  }
390
391  set rowParentId(val) {
392    this.setAttribute('row-parent-id', val || '');
393  }
394
395  set rowHidden(val: boolean) {
396    let height = 0;
397    if (val) {
398      this.setAttribute('row-hidden', '');
399      height = 0;
400    } else {
401      this.removeAttribute('row-hidden');
402      height = this.clientHeight;
403    }
404    if (this.collect) {
405      window.publish(window.SmartEvent.UI.RowHeightChange, {
406        expand: this.funcExpand,
407        value: height,
408      });
409    }
410  }
411
412  get name(): string {
413    return this.getAttribute('name') || '';
414  }
415
416  set name(value: string) {
417    this.setAttribute('name', value);
418  }
419
420  get folder(): boolean {
421    return this.hasAttribute('folder');
422  }
423
424  set folder(value: boolean) {
425    if (value) {
426      this.setAttribute('folder', '');
427      this.folderIcon = document.createElement('lit-icon') as LitIcon;
428      this.folderIcon.classList.add('icon');
429      this.folderIcon.setAttribute('name', 'caret-down');
430      this.folderIcon.setAttribute('size', '19');
431      this.folderIcon.style.display = 'flex';
432      this.describeEl?.insertBefore(this.folderIcon, this.describeEl.children[0]);
433    } else {
434      this.removeAttribute('folder');
435    }
436  }
437
438  get expansion(): boolean {
439    return this.hasAttribute('expansion');
440  }
441
442  fragment: DocumentFragment = document.createDocumentFragment();
443
444  set expansion(value) {
445    if (value === this.expansion) {
446      return;
447    }
448    if (value) {
449      this.updateChildRowStatus();
450    } else {
451      this.childRowToFragment(false);
452    }
453    if (value) {
454      this.setAttribute('expansion', '');
455    } else {
456      this.removeAttribute('expansion');
457    }
458    this.dispatchEvent(
459      new CustomEvent('expansion-change', {
460        detail: {
461          expansion: this.expansion,
462          rowType: this.rowType,
463          rowId: this.rowId,
464          rowParentId: this.rowParentId,
465        },
466      })
467    );
468  }
469
470  childRowToFragment(expansion: boolean): void {
471    for (const childrenRow of this.childrenList) {
472      if (!childrenRow.collect) {
473        this.fragment.append(childrenRow);
474      }
475      if (!expansion) {
476        if (childrenRow.childrenList && childrenRow.folder && childrenRow.expansion) {
477          childrenRow.expansion = false;
478        }
479      }
480    }
481  }
482
483  updateChildRowStatus(): void {
484    this.fragment = document.createDocumentFragment();
485    this.childRowToFragment(true);
486    this.insertAfter(this.fragment, this);
487  }
488
489  clearMemory(): void {
490    this.dataList2 = [];
491    this.dataList = [];
492    this.dataListCache = [];
493    this.fixedList = [];
494    if (this.rootEL) {
495      this.rootEL.innerHTML = '';
496    }
497    if (this.folder) {
498      this.childrenList.forEach((child) => {
499        if (child.clearMemory !== undefined) {
500          child.clearMemory();
501        }
502      });
503      this.childrenList = [];
504    }
505  }
506
507  addTemplateTypes(...type: string[]): void {
508    type.forEach((item) => {
509      this.templateType.add(item);
510    });
511    if (this.hasParentRowEl) {
512      this.toParentAddTemplateType(this);
513    }
514  }
515
516  toParentAddTemplateType = (currentRowEl: TraceRow<any>): void => {
517    let parentRow = currentRowEl.parentRowEl;
518    if (parentRow !== undefined) {
519      currentRowEl.templateType.forEach((item) => {
520        parentRow!.templateType.add(item);
521      });
522      if (parentRow.parentRowEl !== undefined) {
523        this.toParentAddTemplateType(parentRow);
524      }
525    }
526  };
527
528  getHoverStruct(strict: boolean = true, offset: boolean = false, maxKey: string | undefined = undefined): T | undefined {
529    if (this.isHover) {
530      if (maxKey) {
531        let arr =  this.dataListCache.filter(
532          (re) => re.frame && isFrameContainPoint(re.frame, this.hoverX, this.hoverY, strict, offset)
533        ).sort((targetA, targetB) => (targetB as any)[maxKey] - (targetA as any)[maxKey]);
534        return arr[0];
535      } else {
536        return this.dataListCache.find(
537          (re) => re.frame && isFrameContainPoint(re.frame, this.hoverX, this.hoverY, strict, offset)
538        );
539      }
540
541    }
542  }
543
544  addChildTraceRow(child: TraceRow<any>) {
545    TraceRowConfig.allTraceRowList.push(child);
546    child.parentRowEl = this;
547    this.toParentAddTemplateType(child);
548    child.setAttribute('scene', '');
549    this.childrenList.push(child);
550    child.rowHidden = false;
551    this.fragment.appendChild(child);
552  }
553
554  addChildTraceRowAfter(child: TraceRow<any>, targetRow: TraceRow<any>) {
555    TraceRowConfig.allTraceRowList.push(child);
556    child.parentRowEl = this;
557    this.toParentAddTemplateType(child);
558    let index = this.childrenList.indexOf(targetRow);
559    child.setAttribute('scene', '');
560    if (index != -1) {
561      this.childrenList.splice(index + 1, 0, child);
562      child.rowHidden = false;
563      this.fragment.insertBefore(child, this.fragment.childNodes.item(index + 1));
564    } else {
565      this.childrenList.push(child);
566      child.rowHidden = false;
567      this.fragment.append(child);
568    }
569  }
570
571  addChildTraceRowBefore(child: TraceRow<BaseStruct>, targetRow: TraceRow<BaseStruct>) {
572    TraceRowConfig.allTraceRowList.push(child);
573    child.parentRowEl = this;
574    this.toParentAddTemplateType(child);
575    let index = this.childrenList.indexOf(targetRow);
576    child.setAttribute('scene', '');
577    if (index != -1) {
578      this.childrenList.splice(index, 0, child);
579      this.fragment.insertBefore(child, this.fragment.childNodes.item(index));
580    } else {
581      this.childrenList.push(child);
582      child.rowHidden = false;
583      this.fragment.appendChild(child);
584    }
585  }
586
587  addChildTraceRowSpecifyLocation(child: TraceRow<any>, index: number) {
588    TraceRowConfig.allTraceRowList.push(child);
589    child.parentRowEl = this;
590    child.setAttribute('scene', '');
591    this.childrenList.splice(index, 0, child);
592    child.rowHidden = false;
593    this.fragment.insertBefore(child, this.fragment.childNodes.item(index));
594  }
595
596  insertAfter(newEl: DocumentFragment, targetEl: HTMLElement) {
597    let parentEl = targetEl.parentNode;
598    if (parentEl) {
599      if (parentEl!.lastChild === targetEl) {
600        parentEl!.appendChild(newEl);
601      } else {
602        parentEl!.insertBefore(newEl, targetEl.nextSibling);
603      }
604    }
605  }
606
607  set tip(value: string) {
608    if (this.tipEL) {
609      this.tipEL.innerHTML = value;
610    }
611  }
612
613  get frame(): Rect | any {
614    if (this._frame) {
615      this._frame.width = TraceRow.FRAME_WIDTH;
616      this._frame.height = this.clientHeight;
617      return this._frame;
618    } else {
619      this._frame = new Rect(0, 0, TraceRow.FRAME_WIDTH, this.clientHeight || 40);
620      return this._frame;
621    }
622  }
623
624  set frame(f: Rect) {
625    this._frame = f;
626  }
627
628  get checkType(): string {
629    return this.getAttribute('check-type') || '';
630  }
631
632  set checkType(value: string) {
633    if (!value || value.length === 0) {
634      this.removeAttribute('check-type');
635      return;
636    }
637    if (this.getAttribute('check-type') === value) {
638      return;
639    }
640    if (this.folder) {
641      this.childrenList.forEach((it) => (it.checkType = value));
642    }
643    this.setAttribute('check-type', value);
644    if (this.hasAttribute('disabled-check')) {
645      this.checkBoxEL!.style.display = 'none';
646      return;
647    }
648    switch (value) {
649      case '-1':
650        this.checkBoxEL!.style.display = 'none';
651        this.rangeSelect = false;
652        break;
653      case '0':
654        this.checkBoxEL!.style.display = 'flex';
655        this.checkBoxEL!.checked = false;
656        this.checkBoxEL!.indeterminate = false;
657        this.rangeSelect = false;
658        break;
659      case '1':
660        this.checkBoxEL!.style.display = 'flex';
661        this.checkBoxEL!.checked = false;
662        this.checkBoxEL!.indeterminate = true;
663        this.rangeSelect = false;
664        break;
665      case '2':
666        this.rangeSelect = true;
667        this.checkBoxEL!.style.display = 'flex';
668        this.checkBoxEL!.checked = true;
669        this.checkBoxEL!.indeterminate = false;
670        break;
671    }
672  }
673
674  get drawType(): number {
675    return this._drawType;
676  }
677
678  set drawType(value: number) {
679    this._drawType = value;
680    let radioList: NodeListOf<any> = this.shadowRoot!.querySelectorAll('input[type=radio][name=status]');
681    if (radioList!.length > 0) {
682      radioList[Number(value)].checked = true;
683    }
684  }
685
686  get highlight(): boolean {
687    return this.hasAttribute('expansion');
688  }
689
690  set highlight(value: boolean) {
691    if (value) {
692      this.setAttribute('highlight', '');
693    } else {
694      this.removeAttribute('highlight');
695    }
696  }
697
698  set folderPaddingLeft(value: number) {
699    if (this.folderIcon) {
700      this.folderIcon.style.marginLeft = value + 'px';
701    }
702  }
703
704  set folderTextLeft(value: number) {
705    this.nameEL!.style.marginLeft = value + 'px';
706  }
707
708  initElements(): void {
709    this.rootEL = this.shadowRoot?.querySelector('.root');
710    this.checkBoxEL = this.shadowRoot?.querySelector<LitCheckBox>('.lit-check-box');
711    this.collectEL = this.shadowRoot?.querySelector<LitIcon>('.collect');
712    this.describeEl = this.shadowRoot?.querySelector('.describe');
713    this.nameEL = this.shadowRoot?.querySelector('.name');
714    this.canvasVessel = this.shadowRoot?.querySelector('.panel-vessel');
715    this.tipEL = this.shadowRoot?.querySelector('.tip');
716    let canvasNumber = this.args['canvasNumber'];
717    if (!this.args['skeleton']) {
718      for (let i = 0; i < canvasNumber; i++) {
719        let canvas = document.createElement('canvas');
720        canvas.className = 'panel';
721        this.canvas.push(canvas);
722        if (this.canvasVessel) {
723          this.canvasVessel.appendChild(canvas);
724        }
725      }
726    }
727    this.checkBoxEvent();
728    this.describeEl?.addEventListener('click', () => {
729      if (this.folder) {
730        this.expansion = !this.expansion;
731        this.sticky = this.expansion;
732      }
733    });
734    this.funcExpand = true;
735    if (this.rowSettingTree) {
736      this.rowSettingTree.onChange = (e: any): void => {
737        // @ts-ignore
738        this.rowSettingPop!.visible = false;
739        if (this.rowSettingTree?.multiple) {
740          // @ts-ignore
741          this.rowSettingPop!.visible = true;
742        } else {
743          // @ts-ignore
744          this.rowSettingPop!.visible = false;
745        }
746        this.onRowSettingChangeHandler?.(this.rowSettingTree!.getCheckdKeys(), this.rowSettingTree!.getCheckdNodes());
747      };
748    }
749    this.checkType = '-1';
750  }
751
752  private checkBoxEvent(): void {
753    this.checkBoxEL!.onchange = (ev: any) => {
754      info('checkBoxEL onchange ');
755      if (!ev.target.checked) {
756        info('checkBoxEL target not checked');
757        this.rangeSelect = false;
758        this.checkType = '0';
759      } else {
760        this.rangeSelect = true;
761        this.checkType = '2';
762      }
763      this.setCheckBox(ev.target.checked);
764      ev.stopPropagation();
765    };
766    // 防止事件冒泡触发两次describeEl的点击事件
767    this.checkBoxEL!.onclick = (ev: any) => {
768      ev.stopPropagation();
769    };
770  }
771
772  addRowCheckFilePop(): void {
773    this.rowCheckFilePop = document.createElement('litpopover') as LitPopover;
774    this.rowCheckFilePop.innerHTML = `<div slot="content" id="jsonFile" style="display: block;height: auto;max-height:200px;overflow-y:auto">
775    </div>
776    <lit-icon name="copy-csv" size="19" id="myfolder"></lit-icon>
777    <input type="file" id="jsoninput" style="width:0px;height:0px"placeholder=''/>`;
778    this.rowCheckFilePop.id = 'rowCheckFile';
779    this.rowCheckFilePop.className = 'popover checkFile';
780    this.rowCheckFilePop.setAttribute('trigger', 'click');
781    this.rowCheckFilePop?.addEventListener('mouseenter', (e) => {
782      window.publish(window.SmartEvent.UI.HoverNull, undefined);
783    });
784    this.fileEL = this.rowCheckFilePop.querySelector('#jsoninput');
785    this.rowCheckFilePop.onclick = (): void => {
786      this.fileEL.click();
787      this.fileEL.addEventListener(
788        'change',
789        (e: any) => {
790          let file = e.target.files[0];
791          if (file.type === 'application/json') {
792            let file_reader = new FileReader();
793            file_reader.readAsText(file, 'UTF-8');
794            file_reader.onload = () => {
795              let fc = file_reader.result;
796              this.onRowCheckFileChangeHandler?.(fc);
797            };
798          } else {
799            return;
800          }
801        },
802        false
803      );
804    };
805    this.describeEl?.appendChild(this.rowCheckFilePop);
806  }
807
808  addRowSettingPop(): void {
809    this.rowSettingPop = document.createElement('lit-popover') as LitPopover;
810    this.rowSettingPop.innerHTML = `<div slot="content" id="settingList" style="display: block;height: auto;max-height:200px;overflow-y:auto">
811      <lit-tree id="rowSettingTree" checkable="true"></lit-tree>
812      </div>
813      <lit-icon name="setting" size="19" id="setting"></lit-icon>`;
814    this.rowSettingPop.id = 'rowSetting';
815    this.rowSettingPop.className = 'popover setting';
816    this.rowSettingPop.setAttribute('placement', 'bottomLeft');
817    this.rowSettingPop.setAttribute('trigger', 'click');
818    this.rowSettingPop.setAttribute('haveRadio', 'true');
819    this.rowSettingTree = this.rowSettingPop.querySelector('#rowSettingTree') as LitTree;
820    this.rowSettingTree.onChange = (): void => {
821      let isVisible = false;
822      // @ts-ignore
823      this.rowSettingPop!.visible = isVisible;
824      if (this.rowSettingTree?.multiple) {
825        isVisible = true;
826      }
827      // @ts-ignore
828      this.rowSettingPop!.visible = isVisible;
829      this.onRowSettingChangeHandler?.(this.rowSettingTree!.getCheckdKeys(), this.rowSettingTree!.getCheckdNodes());
830    };
831    this.rowSettingPop?.addEventListener('mouseenter', (e) => {
832      window.publish(window.SmartEvent.UI.HoverNull, undefined);
833    });
834    this.describeEl?.appendChild(this.rowSettingPop);
835  }
836
837  getRowSettingKeys(): Array<string> {
838    if (this.rowSetting === 'enable') {
839      return this.rowSettingTree!.getCheckdKeys();
840    }
841    return [];
842  }
843
844  expandFunc(): void {
845    if (this._enableCollapseChart && !this.funcExpand) {
846      this.style.height = `${this.funcMaxHeight}px`;
847      this.funcExpand = true;
848      if (this.collect) {
849        window.publish(window.SmartEvent.UI.RowHeightChange, {
850          expand: this.funcExpand,
851          value: this.funcMaxHeight - 20,
852        });
853      }
854    }
855  }
856
857  enableCollapseChart(): void {
858    this._enableCollapseChart = true;
859    this.nameEL!.onclick = () => {
860      if (this.funcMaxHeight > 20 || this.clientHeight > 20) {
861        if (this.funcExpand) {
862          this.funcMaxHeight = this.clientHeight;
863          this.style.height = '20px';
864          this.funcExpand = false;
865        } else {
866          this.style.height = `${this.funcMaxHeight}px`;
867          this.funcExpand = true;
868        }
869        TraceRow.range!.refresh = true;
870        this.needRefresh = true;
871        this.draw(false);
872        if (this.collect) {
873          window.publish(window.SmartEvent.UI.RowHeightChange, {
874            expand: this.funcExpand,
875            value: this.funcMaxHeight - 20,
876          });
877        }
878      }
879    };
880  }
881
882  initCanvas(list: Array<HTMLCanvasElement>): void {
883    let timerShaftEL = document!
884      .querySelector('body > sp-application')!
885      .shadowRoot!.querySelector('#sp-system-trace')!
886      .shadowRoot!.querySelector('div > timer-shaft-element');
887    let timerShaftCanvas = timerShaftEL!.shadowRoot!.querySelector<HTMLCanvasElement>('canvas');
888    let tempHeight: number = 0;
889    if (this.rowType === TraceRow.ROW_TYPE_FUNC) {
890      tempHeight = 20;
891    } else if (this.rowType === TraceRow.ROW_TYPE_THREAD) {
892      tempHeight = 30;
893    } else if (this.rowType === TraceRow.ROW_TYPE_SYSTEM_ENERGY) {
894      tempHeight = 80;
895    } else if (this.rowType === TraceRow.ROW_TYPE_POWER_ENERGY) {
896      tempHeight = 200;
897    } else if (this.rowType === TraceRow.ROW_TYPE_ANOMALY_ENERGY) {
898      tempHeight = 55;
899    } else {
900      tempHeight = 40;
901    }
902    this.dpr = window.devicePixelRatio || 1;
903    list.forEach((canvas, i) => {
904      this.rootEL!.style.height = `${this.getAttribute('height') || '40'}px`;
905      canvas.style.width = timerShaftCanvas!.style.width;
906      canvas.style.height = tempHeight + 'px';
907      this.canvasWidth = timerShaftCanvas!.width;
908      this.canvasHeight = Math.ceil(tempHeight * this.dpr);
909      canvas.width = this.canvasWidth;
910      canvas.height = this.canvasHeight;
911      // @ts-ignore
912      this.offscreen.push(canvas!.transferControlToOffscreen());
913    });
914  }
915
916  updateWidth(width: number) {
917    this.dpr = window.devicePixelRatio || 1;
918    let tempHeight: number = 0;
919    if (this.rowType === TraceRow.ROW_TYPE_FUNC) {
920      tempHeight = 20;
921    } else if (this.rowType === TraceRow.ROW_TYPE_THREAD) {
922      tempHeight = 30;
923    } else if (this.rowType === TraceRow.ROW_TYPE_SYSTEM_ENERGY) {
924      tempHeight = 90;
925    } else if (this.rowType === TraceRow.ROW_TYPE_POWER_ENERGY) {
926      tempHeight = 200;
927    } else if (this.rowType === TraceRow.ROW_TYPE_ANOMALY_ENERGY) {
928      tempHeight = 55;
929    } else {
930      tempHeight = 40;
931    }
932    if (this.canvas.length > 1) {
933      tempHeight = 20;
934    }
935    this.canvas.forEach((it) => {
936      this.canvasWidth = Math.ceil((width - (this.describeEl?.clientWidth || 248)) * this.dpr);
937      this.canvasHeight = Math.ceil(tempHeight * this.dpr);
938      it!.style.width = width - (this.describeEl?.clientWidth || 248) + 'px';
939      if (this.args.isOffScreen) {
940        this.draw(true);
941      }
942    });
943  }
944
945  drawLine(item: HTMLDivElement, direction: string /*string[top|bottom]*/) {
946    if (!item) return;
947    switch (direction) {
948      case 'top':
949        item.classList.remove('line-bottom');
950        item.classList.add('line-top');
951        break;
952      case 'bottom':
953        item.classList.remove('line-top');
954        item.classList.add('line-bottom');
955        break;
956      case '':
957        item.classList.remove('line-top');
958        item.classList.remove('line-bottom');
959        break;
960    }
961  }
962
963  connectedCallback() {
964    this.describeEl!.ondragstart = (ev: DragEvent) => this.rowDragstart(ev);
965    this.describeEl!.ondragleave = (ev: any) => {
966      this.drawLine(ev.currentTarget, '');
967      return undefined;
968    };
969    this.describeElEvent();
970    this.collectEL!.onclick = (e) => {
971      if (this.isComplete) {
972        this.collect = !this.collect;
973        if (this.collect) {
974          this.describeEl!.draggable = false;
975        } else {
976          this.describeEl!.draggable = false;
977        }
978        document.dispatchEvent(
979          new CustomEvent('collect', {
980            detail: {
981              type: e.type,
982              row: this,
983            },
984          })
985        );
986        this.favoriteChangeHandler?.(this);
987      }
988    };
989    if (!this.args['skeleton']) {
990      this.initCanvas(this.canvas);
991    }
992  }
993
994  private describeElEvent(): void {
995    this.describeEl!.ondragend = (ev: any) => {
996      rowDragElement = null;
997      ev.target.classList.remove('drag');
998      this.drawLine(ev.currentTarget, '');
999      return undefined;
1000    };
1001    this.describeEl!.ondragover = (ev: any) => {
1002      if (!this.collect) return;
1003      if (rowDragElement === this) return;
1004      let rect = ev.currentTarget.getBoundingClientRect();
1005      if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) {
1006        //上面
1007        dragDirection = 'top';
1008        this.drawLine(ev.currentTarget, 'top');
1009      } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) {
1010        //下面
1011        dragDirection = 'bottom';
1012        this.drawLine(ev.currentTarget, 'bottom');
1013      }
1014      return undefined;
1015    };
1016    this.describeEl!.ondrop = (ev: any) => {
1017      if (!this.collect) return;
1018      this.drawLine(ev.currentTarget, '');
1019      let spacer = this.parentElement!.previousElementSibling! as HTMLDivElement;
1020      let startDragNode = collectList.findIndex((it) => it === rowDragElement);
1021      let endDragNode = collectList.findIndex((it) => it === this);
1022      if (startDragNode === -1 || endDragNode === -1) return;
1023      if (startDragNode < endDragNode && dragDirection === 'top') {
1024        endDragNode--;
1025      } else if (startDragNode > endDragNode && dragDirection === 'bottom') {
1026        endDragNode++;
1027      }
1028      collectList.splice(endDragNode, 0, ...collectList.splice(startDragNode, 1));
1029      collectList.forEach((it, i) => {
1030        if (i === 0) {
1031          it.style.top = `${spacer.offsetTop + 48}px`;
1032        } else {
1033          it.style.top = `${collectList[i - 1].offsetTop + collectList[i - 1].offsetHeight}px`;
1034        }
1035      });
1036    };
1037  }
1038
1039  rowDragstart(ev: any) {
1040    rowDragElement = this;
1041    ev.target.classList.add('drag');
1042  }
1043
1044  setCheckBox(isCheck: boolean) {
1045    if (this.folder) {
1046      // favorite row  check change;
1047      window.publish(window.SmartEvent.UI.CheckALL, {
1048        rowId: this.rowId,
1049        isCheck: isCheck,
1050      });
1051      this.childrenList!.forEach((ck) => {
1052        ck.setAttribute('check-type', isCheck ? '2' : '0');
1053        let allCheck: LitCheckBox | null | undefined = ck?.shadowRoot?.querySelector('.lit-check-box');
1054        if (allCheck) {
1055          allCheck!.checked = isCheck;
1056        }
1057      });
1058    }
1059    this.selectChangeHandler?.(this);
1060  }
1061
1062  onMouseHover(x: number, y: number, tip: boolean = true): T | undefined | null {
1063    if (this.tipEL) {
1064      this.tipEL.style.display = 'none';
1065    }
1066    return null;
1067  }
1068
1069  setTipLeft(x: number, struct: any) {
1070    if (struct === null && this.tipEL) {
1071      this.tipEL.style.display = 'none';
1072      return;
1073    }
1074    if (this.tipEL) {
1075      this.tipEL.style.display = 'flex';
1076      if (x + this.tipEL.clientWidth > (this.canvasVessel!.clientWidth || 0)) {
1077        this.tipEL.style.transform = `translateX(${x - this.tipEL.clientWidth - 1}px)`;
1078      } else {
1079        this.tipEL.style.transform = `translateX(${x}px)`;
1080      }
1081    }
1082  }
1083
1084  onMouseLeave(x: number, y: number) {
1085    if (this.tipEL) {
1086      this.tipEL.style.display = 'none';
1087    }
1088  }
1089
1090  loadingPin1: number = 0;
1091  loadingPin2: number = 0;
1092  static currentActiveRows:Array<string> = [];
1093  drawFrame(): void {
1094    if (!this.hasAttribute('row-hidden')) {
1095      if (!this.loadingFrame || window.isLastFrame || !this.isComplete) {
1096        if (this.needRefresh || window.isLastFrame) {
1097          this.loadingFrame = true;
1098          this.needRefresh = false;
1099          this.loadingPin1 = TraceRow.range?.startNS || 0;
1100          this.loadingPin2 = TraceRow.range?.endNS || 0;
1101          TraceRow.currentActiveRows.push(`${this.rowType}-${this.rowId}`);
1102          this.supplierFrame!().then((res) => {
1103            if (this.onComplete) {
1104              this.onComplete();
1105              this.onComplete = undefined;
1106            }
1107            this.dataListCache = res;
1108            this.dataListCache.push(...this.fixedList);
1109            this.isComplete = true;
1110            this.loadingFrame = false;
1111            let idx = TraceRow.currentActiveRows.findIndex(it=> it === `${ this.rowType }-${ this.rowId }`)
1112            if (idx!=-1){
1113              TraceRow.currentActiveRows.splice(idx, 1);
1114            }
1115            requestAnimationFrame(() => {
1116              this.onThreadHandler?.(true, null);
1117              if (TraceRow.currentActiveRows.isEmpty()){
1118                window.publish(window.SmartEvent.UI.LoadFinish,"");
1119              }
1120              window.publish(window.SmartEvent.UI.LoadFinishFrame,"");
1121            });
1122          });
1123        } else if (this.fixedList.length > 0 && !this.dataListCache.includes(this.fixedList[0])) {
1124          this.dataListCache.push(this.fixedList[0]);
1125        }
1126      }
1127      this.onThreadHandler?.(true, null);
1128    }
1129  }
1130  draw(useCache: boolean = false) {
1131    this.dpr = window.devicePixelRatio || 1;
1132    if (this.sleeping) {
1133      return;
1134    }
1135    if (this.supplierFrame) {
1136      //如果设置了实时渲染,则调用drawFrame
1137      this.drawFrame();
1138      return;
1139    }
1140    if (this.online) {
1141      if (!useCache && !TraceRow.isUserInteraction) {
1142        this.supplier?.().then((res) => {
1143          this.onThreadHandler?.(useCache, res as any);
1144        });
1145      }
1146      this.onThreadHandler?.(useCache, null);
1147      return;
1148    }
1149    if (!this.isComplete) {
1150      if (this.supplier && !this.isLoading) {
1151        this.isLoading = true;
1152        this.must = true;
1153        let promise = this.supplier();
1154        if (promise) {
1155          promise.then((res) => {
1156            this.dataList = res;
1157            if (this.onComplete) {
1158              this.onComplete();
1159            }
1160            window.publish(window.SmartEvent.UI.TraceRowComplete, this);
1161            this.isComplete = true;
1162            this.isLoading = false;
1163            this.draw(false);
1164          });
1165        } else {
1166          this.isLoading = false;
1167          this.draw(false);
1168        }
1169      }
1170    } else {
1171      if (!this.hasAttribute('row-hidden')) {
1172        if (this.onThreadHandler && this.dataList) {
1173          this.onThreadHandler!(false, null);
1174        }
1175      }
1176    }
1177  }
1178
1179  canvasSave(ctx: CanvasRenderingContext2D) {
1180    ctx.save();
1181    ctx.translate(0, this.translateY);
1182    const clipRect = new Path2D();
1183    clipRect.rect(0, 0, this.frame.width, this.frame.height);
1184    ctx.clip(clipRect);
1185  }
1186
1187  canvasRestore(ctx: CanvasRenderingContext2D, trace?: SpSystemTrace | null) {
1188    drawSelectionRange(ctx, this);
1189    ctx.restore();
1190  }
1191
1192  clearCanvas(ctx: CanvasRenderingContext2D) {
1193    if (ctx) {
1194      this.canvas.forEach((it) => {
1195        ctx.clearRect(0, 0, it!.clientWidth || 0, it!.clientHeight || 0);
1196      });
1197    }
1198  }
1199
1200  drawLines(ctx: CanvasRenderingContext2D) {
1201    if (ctx) {
1202      ctx.lineWidth = 1;
1203      ctx.strokeStyle = this.getLineColor();
1204      TraceRow.range?.xs.forEach((it) => {
1205        ctx.moveTo(Math.floor(it), 0);
1206        ctx.lineTo(Math.floor(it), this.shadowRoot?.host.clientHeight || 0);
1207      });
1208      ctx.stroke();
1209    }
1210  }
1211
1212  getLineColor() {
1213    return window.getComputedStyle(this.rootEL!, null).getPropertyValue('border-bottom-color');
1214  }
1215
1216  drawSelection(ctx: CanvasRenderingContext2D) {
1217    if (this.rangeSelect) {
1218      TraceRow.rangeSelectObject!.startX = Math.floor(
1219        ns2x(
1220          TraceRow.rangeSelectObject!.startNS!,
1221          TraceRow.range!.startNS,
1222          TraceRow.range!.endNS,
1223          TraceRow.range!.totalNS!,
1224          this.frame
1225        )
1226      );
1227      TraceRow.rangeSelectObject!.endX = Math.floor(
1228        ns2x(
1229          TraceRow.rangeSelectObject!.endNS!,
1230          TraceRow.range!.startNS,
1231          TraceRow.range!.endNS,
1232          TraceRow.range!.totalNS!,
1233          this.frame
1234        )
1235      );
1236      if (ctx) {
1237        ctx.globalAlpha = 0.5;
1238        ctx.fillStyle = '#666666';
1239        ctx.fillRect(
1240          TraceRow.rangeSelectObject!.startX!,
1241          this.frame.y,
1242          TraceRow.rangeSelectObject!.endX! - TraceRow.rangeSelectObject!.startX!,
1243          this.frame.height
1244        );
1245        ctx.globalAlpha = 1;
1246      }
1247    }
1248  }
1249
1250  isInTimeRange(startTime: number, duration: number): boolean {
1251    return (
1252      (startTime || 0) + (duration || 0) > (TraceRow.range?.startNS || 0) &&
1253      (startTime || 0) < (TraceRow.range?.endNS || 0)
1254    );
1255  }
1256
1257  buildArgs(obj: any) {
1258    let result: any = {
1259      list: this.must ? this.dataList : undefined,
1260      offscreen: !this.isTransferCanvas ? this.offscreen[0] : undefined, //是否离屏
1261      dpr: this.dpr, //屏幕dpr值
1262      xs: TraceRow.range?.xs, //线条坐标信息
1263      isHover: this.isHover,
1264      hoverX: this.hoverX,
1265      hoverY: this.hoverY,
1266      canvasWidth: this.canvasWidth,
1267      canvasHeight: this.canvasHeight,
1268      isRangeSelect: this.rangeSelect,
1269      rangeSelectObject: TraceRow.rangeSelectObject,
1270      lineColor: this.getLineColor(),
1271      chartColor: ColorUtils.MD_PALETTE[0],
1272      startNS: TraceRow.range?.startNS || 0,
1273      endNS: TraceRow.range?.endNS || 0,
1274      totalNS: TraceRow.range?.totalNS || 0,
1275      slicesTime: TraceRow.range?.slicesTime,
1276      range: TraceRow.range,
1277      frame: this.frame,
1278      flagMoveInfo: null,
1279      flagSelectedInfo: null,
1280      wakeupBean: null,
1281    };
1282    Reflect.ownKeys(obj).forEach((it) => {
1283      result[it] = obj[it];
1284    });
1285    return result;
1286  }
1287
1288  getTransferArray() {
1289    let tsf = [];
1290    if (!this.isTransferCanvas) {
1291      tsf.push(this.offscreen[0]);
1292    }
1293    if (this.must && this.dataList instanceof ArrayBuffer) {
1294      tsf.push(this.dataList);
1295    }
1296    return tsf;
1297  }
1298
1299  attributeChangedCallback(name: string, oldValue: string, newValue: string) {
1300    switch (name) {
1301      case 'name':
1302        if (this.nameEL) {
1303          this.nameEL.textContent = newValue;
1304          this.nameEL.title = newValue;
1305        }
1306        break;
1307      case 'height':
1308        if (newValue != oldValue) {
1309          if (!this.args.isOffScreen) {
1310          }
1311        }
1312        break;
1313      case 'check-type':
1314        if (newValue === 'check') {
1315          this.checkBoxEL?.setAttribute('checked', '');
1316        } else {
1317          this.checkBoxEL?.removeAttribute('checked');
1318        }
1319        break;
1320    }
1321  }
1322
1323  focusContain(e: MouseEvent, inFavoriteArea: boolean): boolean {
1324    let _y = (e.currentTarget as HTMLElement).getBoundingClientRect().y;
1325    let myRect = this.getBoundingClientRect();
1326    let x = e.offsetX;
1327    let y = e.offsetY + _y;
1328    if (x >= myRect.x && x <= myRect.x + myRect.width && y >= myRect.y && y <= myRect.y + myRect.height) {
1329      this.hoverX = x - this.describeEl!.clientWidth;
1330      this.hoverY = y - myRect.y;
1331      this.isHover = this.collect === inFavoriteArea;
1332      return true;
1333    } else {
1334      this.isHover = false;
1335      if (this.tipEL) {
1336        this.tipEL.style.display = 'none';
1337      }
1338      return false;
1339    }
1340  }
1341
1342  initHtml(): string {
1343    return TraceRowHtml;
1344  }
1345}
1346