• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { BaseElement, element } from '../../../base-ui/BaseElement';
17import { TraceRow } from './base/TraceRow';
18import { dpr } from './base/Extension';
19import {
20  drawFlagLineSegment,
21  drawLines,
22  drawLinkLines,
23  drawLogsLineSegment,
24  drawWakeUp,
25  drawWakeUpList,
26  PairPoint,
27  Rect,
28} from '../../database/ui-worker/ProcedureWorkerCommon';
29import { Flag } from './timer-shaft/Flag';
30import { TimerShaftElement } from './TimerShaftElement';
31import { CpuStruct } from '../../database/ui-worker/cpu/ProcedureWorkerCPU';
32import { WakeupBean } from '../../bean/WakeupBean';
33import { LitIcon } from '../../../base-ui/icon/LitIcon';
34import { SpSystemTrace } from '../SpSystemTrace';
35
36const maxScale = 0.8; //收藏最大高度为界面最大高度的80%
37const topHeight = 150; // 顶部cpu使用率部分高度固定为150px
38const minHeight = 40; //泳道最低高度为40
39const mouseMoveRange = 5;
40
41@element('sp-chart-list')
42export class SpChartList extends BaseElement {
43  private static COLLECT_G1 = '1';
44  private static COLLECT_G2 = '2';
45  private collectEl1: HTMLDivElement | null | undefined;
46  private collectEl2: HTMLDivElement | null | undefined;
47  private groupTitle1: HTMLDivElement | null | undefined;
48  private groupTitle2: HTMLDivElement | null | undefined;
49  private icon1: LitIcon | null | undefined;
50  private icon2: LitIcon | null | undefined;
51  private removeCollectIcon1: LitIcon | null | undefined;
52  private removeCollectIcon2: LitIcon | null | undefined;
53  private rootEl: HTMLDivElement | null | undefined;
54  private fragmentGroup1: DocumentFragment = document.createDocumentFragment();
55  private fragmentGroup2: DocumentFragment = document.createDocumentFragment();
56  private canvas: HTMLCanvasElement | null | undefined; //绘制收藏泳道图
57  private canvasCtx: CanvasRenderingContext2D | undefined | null;
58  private canResize: boolean = false;
59  private isPress: boolean = false;
60  private startPageY = 0;
61  private startClientHeight: number = 0;
62  private scrollTimer: unknown;
63  collect1Expand: boolean = true;
64  collect2Expand: boolean = true;
65  // @ts-ignore
66  private collectRowList1: Array<TraceRow<unknown>> = [];
67  // @ts-ignore
68  private collectRowList2: Array<TraceRow<unknown>> = [];
69  private maxHeight = 0;
70  private manualHeight = 0;
71  private spSystemTrace: SpSystemTrace | undefined | null;
72
73  initElements(): void {
74    this.spSystemTrace = document?.querySelector('body > sp-application')?.shadowRoot?.querySelector('#sp-system-trace');
75    this.collectEl1 = this.shadowRoot?.querySelector<HTMLDivElement>('#collect-group-1');
76    this.collectEl2 = this.shadowRoot?.querySelector<HTMLDivElement>('#collect-group-2');
77    this.groupTitle1 = this.shadowRoot?.querySelector<HTMLDivElement>('#group-1-title');
78    this.groupTitle2 = this.shadowRoot?.querySelector<HTMLDivElement>('#group-2-title');
79    this.icon1 = this.shadowRoot?.querySelector<LitIcon>('#group_1_expand');
80    this.icon2 = this.shadowRoot?.querySelector<LitIcon>('#group_2_expand');
81    this.removeCollectIcon1 = this.shadowRoot?.querySelector<LitIcon>('#group_1_collect');
82    this.removeCollectIcon2 = this.shadowRoot?.querySelector<LitIcon>('#group_2_collect');
83    this.rootEl = this.shadowRoot?.querySelector<HTMLDivElement>('.root');
84    this.canvas = this.shadowRoot?.querySelector<HTMLCanvasElement>('.panel-canvas');
85    this.canvasCtx = this.canvas?.getContext('2d'); //@ts-ignore
86    window.subscribe(window.SmartEvent.UI.RowHeightChange, (data: { expand: number; value: number }) => {
87      this.resizeHeight();
88      if (!data.expand) {
89        let offset = this.scrollTop - data.value;
90        offset = offset < 0 ? 0 : offset;
91        this.scrollTop = offset;
92      }
93      this.refreshFavoriteCanvas();
94    });
95    this.initChartListListener();
96  }
97
98  private initChartListListener(): void {
99    let offsetYTimeOut: unknown = undefined;
100    const foldCollect1 = (): void => {
101      if (offsetYTimeOut) {
102        //@ts-ignore
103        clearTimeout(offsetYTimeOut);
104      }
105      this.collect1Expand = !this.collect1Expand;
106      if (this.collect1Expand) {
107        this.icon1!.style.transform = 'rotateZ(0deg)';
108        this.collectEl1?.appendChild(this.fragmentGroup1);
109        if (!this.collect2Expand) { // G1展开,G2折叠时处理连线y坐标
110          this.handleCollect2LinkNodeY();
111        }
112      } else {
113        this.icon1!.style.transform = 'rotateZ(-90deg)';
114        this.collectRowList1.forEach((row) => this.fragmentGroup1.appendChild(row));
115        offsetYTimeOut = setTimeout(() => { //折叠G1收藏栏,连线处理
116          this.handleCollect1LinkNodeY();
117          if (!this.collect2Expand) {
118            this.handleCollect2LinkNodeY();
119          }
120          this.spSystemTrace?.refreshCanvas(true);
121        }, 50);
122      }
123      this.resizeHeight();
124    };
125    this.icon1?.addEventListener('click', () => foldCollect1());
126    const foldCollect2 = (): void => {
127      this.collect2Expand = !this.collect2Expand;
128      if (this.collect2Expand) {
129        this.icon2!.style.transform = 'rotateZ(0deg)';
130        this.collectEl2?.appendChild(this.fragmentGroup2);
131        this.scrollTop = this.scrollHeight;
132      } else {
133        this.icon2!.style.transform = 'rotateZ(-90deg)';
134        this.collectRowList2.forEach((row) => this.fragmentGroup2.appendChild(row));
135        this.scrollTop = 0;
136        offsetYTimeOut = setTimeout(() => {
137          this.handleCollect2LinkNodeY();
138          this.spSystemTrace?.refreshCanvas(true);
139        }, 50);
140      }
141      this.resizeHeight();
142    };
143    this.icon2?.addEventListener('click', () => foldCollect2());
144    document.addEventListener('keyup', (e) => {
145      if (e.key.toLowerCase() === 'b' && e.ctrlKey === false && this.spSystemTrace?.keyboardEnable) {
146        // 收藏夹有泳道时 为true
147        const hasChildNode1 = this.collectEl1?.hasChildNodes() || this.fragmentGroup1.hasChildNodes();
148        const hasChildNode2 = this.collectEl2?.hasChildNodes() || this.fragmentGroup2.hasChildNodes();
149        // 两个收藏夹都有泳道时
150        if (hasChildNode1 && hasChildNode2) {
151          const flag = this.collect1Expand === this.collect2Expand;
152          if (flag) {
153            foldCollect1();
154            foldCollect2();
155          } else {
156            // 两收藏夹的折叠状态不一致 优先一起折叠
157            if (this.collect1Expand) {
158              foldCollect1();
159            }
160            else {
161              foldCollect2();
162            }
163          }
164          return;
165        }
166        // 只影响有泳道的收藏夹
167        if (hasChildNode1) {
168          foldCollect1();
169        }
170        if (hasChildNode2) {
171          foldCollect2();
172        }
173      }
174    });
175
176    this.removeCollectIcon1?.addEventListener('click', () => {
177      Array.from(this.collectRowList1).forEach(row => {
178        row.collectEL?.click();
179      });
180    });
181    this.removeCollectIcon2?.addEventListener('click', () => {
182      Array.from(this.collectRowList2).forEach(row => {
183        row.collectEL?.click();
184      });
185    });
186  }
187
188    // 处理G1收藏栏折叠时,连线的y坐标
189    private handleCollect1LinkNodeY(): void {
190      this.spSystemTrace?.linkNodes?.forEach(linkItem => {
191        if (linkItem[0].rowEL.collectGroup === linkItem[1].rowEL.collectGroup && linkItem[1].rowEL.collectGroup === '1') { // 起点终点都在G1
192          linkItem[0].rowEL.translateY = 23;
193          linkItem[1].rowEL.translateY = 23;
194        } else if (linkItem[0].rowEL.collectGroup !== linkItem[1].rowEL.collectGroup) { // 起点终点不在同个收藏栏
195          if (linkItem[0].rowEL.collectGroup === '1') {
196            linkItem[0].rowEL.translateY = 23;
197          } else if (linkItem[1].rowEL.collectGroup === '1') {
198            linkItem[1].rowEL.translateY = 23;
199          }
200        }
201      });
202    }
203
204    // 处理G2收藏栏折叠时,连线的y坐标
205    private handleCollect2LinkNodeY(): void {
206      this.spSystemTrace?.linkNodes?.forEach(linkItem => {
207        if (linkItem[0].rowEL.collectGroup === linkItem[1].rowEL.collectGroup && linkItem[1].rowEL.collectGroup === '2') { // 起点终点都在G2
208          linkItem[0].rowEL.translateY = 23;
209          linkItem[1].rowEL.translateY = 23;
210        } else if (linkItem[0].rowEL.collectGroup !== linkItem[1].rowEL.collectGroup) { // 起点终点不在同个收藏栏
211          if (linkItem[0].rowEL.collectGroup === '2') {
212            linkItem[0].rowEL.translateY = Number(this.groupTitle1?.clientHeight) + Number(this.collectEl1?.clientHeight) + 27;
213          } else if (linkItem[1].rowEL.collectGroup === '2') {
214            linkItem[1].rowEL.translateY = Number(this.groupTitle1?.clientHeight) + Number(this.collectEl1?.clientHeight) + 27;
215          }
216        }
217      });
218    }
219
220  removeAllCollectRow(): void {
221    Array.from(this.collectRowList1).forEach(row => {
222      row.collectEL?.click();
223    });
224    Array.from(this.collectRowList2).forEach(row => {
225      row.collectEL?.click();
226    });
227  }
228
229  private resizeHeight(): void {
230    this.maxHeight = 0;
231    // @ts-ignore
232    this.collectEl1!.childNodes.forEach((item) => (this.maxHeight += (item as unknown).clientHeight));
233    // @ts-ignore
234    this.collectEl2!.childNodes.forEach((item) => (this.maxHeight += (item as unknown).clientHeight));
235    if (this.groupTitle1) {
236      this.maxHeight += this.groupTitle1.clientHeight;
237    }
238    if (this.groupTitle2) {
239      this.maxHeight += this.groupTitle2.clientHeight;
240    }
241
242    this.maxHeight = Math.min(this.getMaxLimitHeight(), this.maxHeight);
243    if (this.manualHeight > 0) {
244      this.style.height = `${Math.min(this.maxHeight, this.manualHeight)}px`;
245    } else {
246      this.style.height = `${this.maxHeight}px`;
247    }
248  }
249
250  private getMaxLimitHeight(): number {
251    return (this.parentElement!.clientHeight - topHeight) * maxScale;
252  }
253
254  // @ts-ignore
255  getCollectRows(filter?: (row: TraceRow<unknown>) => boolean): Array<TraceRow<unknown>> | [] {
256    if (filter) {
257      return [...this.collectRowList1.filter(filter), ...this.collectRowList2.filter(filter)];
258    } else {
259      return this.getAllCollectRows();
260    }
261  }
262
263  getRowScrollTop(): number {
264    return this.rootEl?.scrollTop || 0;
265  }
266
267  // @ts-ignore
268  expandSearchRowGroup(row: TraceRow<unknown>): void {
269    this.updateGroupDisplay();
270    if (row.collectGroup === SpChartList.COLLECT_G1) {
271      if (!this.collect1Expand) {
272        this.collect1Expand = true;
273        this.icon1!.style.transform = 'rotateZ(0deg)';
274        this.collectEl1?.appendChild(this.fragmentGroup1);
275      }
276    } else {
277      if (!this.collect2Expand) {
278        this.collect2Expand = true;
279        this.icon2!.style.transform = 'rotateZ(0deg)';
280        this.collectEl2?.appendChild(this.fragmentGroup2);
281        this.scrollTop = this.scrollHeight;
282      }
283    }
284    this.resizeHeight();
285  }
286
287  // @ts-ignore
288  getCollectRow(filter: (row: TraceRow<unknown>) => boolean): TraceRow<unknown> | undefined {
289    return this.collectRowList1.find(filter) || this.collectRowList2.find(filter);
290  }
291
292  // @ts-ignore
293  getAllCollectRows(): Array<TraceRow<unknown>> {
294    return [...this.collectRowList1, ...this.collectRowList2];
295  }
296
297  getCollectRowsInfo(group: string): unknown {
298    return (group === SpChartList.COLLECT_G1 ? this.collectRowList1 : this.collectRowList2).map((row) => {
299      let rowJson = {
300        type: row.rowType,
301        name: row.name,
302        id: row.rowId,
303        parents: [],
304      };
305      this.getRowParent(rowJson, row);
306      rowJson.parents.reverse();
307      return rowJson;
308    });
309  }
310
311  // @ts-ignore
312  getRowParent(obj: unknown, row: TraceRow<unknown>): void {
313    if (row.parentRowEl) {
314      // @ts-ignore
315      if (obj.parents) {
316        let parent: unknown = {
317          type: row.parentRowEl.rowType,
318          name: row.parentRowEl.name,
319          id: row.parentRowEl.rowId,
320        };
321        // @ts-ignore
322        (obj.parents as Array<unknown>).push(parent);
323      } else {
324        // @ts-ignore
325        obj.parents = [parent];
326      }
327      this.getRowParent(obj, row.parentRowEl);
328    }
329  }
330
331  // @ts-ignore
332  getAllSelectCollectRows(): Array<TraceRow<unknown>> {
333    // @ts-ignore
334    const rows: Array<TraceRow<unknown>> = [];
335    for (const row of this.collectRowList1) {
336      if (row.checkType === '2') {
337        rows.push(row);
338      }
339    }
340    for (const row of this.collectRowList2) {
341      if (row.checkType === '2') {
342        rows.push(row);
343      }
344    }
345    return rows;
346  }
347
348  insertRowBefore(node: Node, child: Node): void {
349    // @ts-ignore
350    if (child === null || (child as TraceRow<unknown>).collectGroup === (node as TraceRow<unknown>).collectGroup) {
351      // @ts-ignore
352      if ((node as TraceRow<unknown>).collectGroup === SpChartList.COLLECT_G1) {
353        this.collectEl1!.insertBefore(node, child);
354        // @ts-ignore
355        this.collectRowList1 = Array.from(this.collectEl1!.children) as TraceRow<unknown>[];
356      } else {
357        this.collectEl2!.insertBefore(node, child);
358        // @ts-ignore
359        this.collectRowList2 = Array.from(this.collectEl2!.children) as TraceRow<unknown>[];
360      }
361    }
362  }
363
364  reset(): void {
365    this.maxHeight = 0;
366    this.clearRect();
367    this.collect1Expand = true;
368    this.collect2Expand = true;
369    this.icon1!.style.transform = 'rotateZ(0deg)';
370    this.icon2!.style.transform = 'rotateZ(0deg)';
371    this.collectRowList1.forEach((row) => {
372      row.clearMemory();
373    });
374    this.collectRowList2.forEach((row) => {
375      row.clearMemory();
376    });
377    this.collectRowList1 = [];
378    this.collectRowList2 = [];
379    this.fragmentGroup1 = document.createDocumentFragment();
380    this.fragmentGroup2 = document.createDocumentFragment();
381    this.collectEl1!.innerHTML = '';
382    this.collectEl2!.innerHTML = '';
383    this.updateGroupDisplay();
384    this.style.height = 'auto';
385  }
386
387  context(): CanvasRenderingContext2D | undefined | null {
388    return this.canvasCtx;
389  }
390
391  getCanvas(): HTMLCanvasElement | null | undefined {
392    return this.canvas;
393  }
394
395  connectedCallback(): void {
396    super.connectedCallback();
397    const vessel = this.parentNode as HTMLDivElement;
398    vessel.addEventListener('mousedown', this.onMouseDown);
399    vessel.addEventListener('mouseup', this.onMouseUp);
400    vessel.addEventListener('mousemove', this.onMouseMove);
401    this.addEventListener('scroll', this.onScroll, { passive: true });
402  }
403
404  disconnectedCallback(): void {
405    super.disconnectedCallback();
406    const vessel = this.parentNode as HTMLDivElement;
407    vessel.removeEventListener('mousedown', this.onMouseDown);
408    vessel.removeEventListener('mouseup', this.onMouseUp);
409    vessel.removeEventListener('mousemove', this.onMouseMove);
410    this.removeEventListener('scroll', this.onScroll);
411  }
412
413  onScroll = (ev: Event): void => {
414    this.canvas!.style.transform = `translateY(${this.scrollTop}px)`;
415    if (this.scrollTimer) {
416      // @ts-ignore
417      clearTimeout(this.scrollTimer);
418    }
419    this.scrollTimer = setTimeout(() => {
420      TraceRow.range!.refresh = true;
421      window.publish(window.SmartEvent.UI.RefreshCanvas, {});
422    }, 100);
423    window.publish(window.SmartEvent.UI.RefreshCanvas, {});
424  };
425
426  onMouseDown = (ev: MouseEvent): void => {
427    this.isPress = true;
428    this.startPageY = ev.pageY;
429    this.startClientHeight = this.clientHeight;
430    if (this.containPoint(ev)) {
431      if (
432        this.getBoundingClientRect().bottom > ev.pageY - mouseMoveRange &&
433        this.getBoundingClientRect().bottom < ev.pageY + mouseMoveRange
434      ) {
435        this.style.cursor = 'row-resize';
436        this.canResize = true;
437      } else {
438        this.style.cursor = 'default';
439        this.canResize = false;
440      }
441      // @ts-ignore
442      (window as unknown).collectResize = this.canResize;
443    }
444  };
445
446  onMouseMove = (ev: MouseEvent): void => {
447    if (this.containPoint(ev)) {
448      let inResizeArea =
449        this.getBoundingClientRect().bottom > ev.pageY - mouseMoveRange &&
450        this.getBoundingClientRect().bottom < ev.pageY + mouseMoveRange;
451      if ((this.isPress && this.canResize) || inResizeArea) {
452        this.style.cursor = 'row-resize';
453      } else {
454        this.style.cursor = 'default';
455      }
456    }
457    //防止点击触发move时间
458    if (Math.abs(ev.pageY - this.startPageY) < 2) {
459      return;
460    }
461    if (this.canResize && this.isPress) {
462      // @ts-ignore
463      (window as unknown).collectResize = true;
464      // 拖动超过所有泳道最大高度 或小于一个泳道的高度,不支持拖动
465      let newHeight = this.startClientHeight + ev.pageY - this.startPageY;
466      if (newHeight > this.maxHeight) {
467        newHeight = this.maxHeight;
468      }
469      if (newHeight > this.getMaxLimitHeight()) {
470        newHeight = this.getMaxLimitHeight();
471      }
472      if (newHeight < minHeight) {
473        newHeight = minHeight;
474      }
475      this!.style.height = `${newHeight}px`;
476      this.manualHeight = newHeight;
477    } else {
478      // @ts-ignore
479      (window as unknown).collectResize = false;
480    }
481  };
482
483  onMouseUp = (ev: MouseEvent): void => {
484    this.isPress = false;
485    this.canResize = false;
486    this.style.cursor = 'default';
487    // @ts-ignore
488    (window as unknown).collectResize = false;
489    if (this.style.display === 'flex') {
490      this.refreshFavoriteCanvas();
491    }
492  };
493
494  // @ts-ignore
495  insertRow(row: TraceRow<unknown>, group: string, updateGroup: boolean): void {
496    this.style.display = 'flex';
497    let collectGroup = !updateGroup && row.collectGroup ? row.collectGroup : group;
498    if (row.collectGroup !== SpChartList.COLLECT_G1 && row.collectGroup !== SpChartList.COLLECT_G2) {
499      row.collectGroup = group;
500    }
501    if (updateGroup) {
502      row.collectGroup = group;
503    }
504    if (collectGroup === SpChartList.COLLECT_G1) {
505      if (!this.collect1Expand) {
506        this.collect1Expand = true;
507        this.icon1!.style.transform = 'rotateZ(0deg)';
508      }
509      if (this.collectRowList1.indexOf(row) === -1) {
510        this.collectRowList1.push(row);
511      }
512      if (!this.fragmentGroup1.contains(row)) {
513        this.fragmentGroup1.appendChild(row);
514      }
515      this.collectEl1?.appendChild(this.fragmentGroup1);
516      this.scrollTo({ top: this.collectEl1?.clientHeight });
517    } else {
518      if (!this.collect2Expand) {
519        this.collect2Expand = true;
520        this.icon2!.style.transform = 'rotateZ(0deg)';
521      }
522      if (this.collectRowList2.indexOf(row) === -1) {
523        this.collectRowList2.push(row);
524      }
525      if (!this.fragmentGroup2.contains(row)) {
526        this.fragmentGroup2.appendChild(row);
527      }
528      this.collectEl2!.appendChild(this.fragmentGroup2);
529      this.scrollTo({ top: this.scrollHeight });
530    }
531    this.updateGroupDisplay();
532    this.resizeHeight();
533    this.refreshFavoriteCanvas();
534    row.currentContext = this.canvasCtx;
535  }
536
537  // @ts-ignore
538  deleteRow(row: TraceRow<unknown>, clearCollectGroup: boolean): void {
539    if (row.collectGroup === SpChartList.COLLECT_G1) {
540      this.collectRowList1.splice(this.collectRowList1.indexOf(row), 1);
541      if (!this.fragmentGroup1.contains(row)) {
542        this.fragmentGroup1.appendChild(row);
543      }
544      this.fragmentGroup1.removeChild(row);
545    } else {
546      this.collectRowList2.splice(this.collectRowList2.indexOf(row), 1);
547      if (!this.fragmentGroup2.contains(row)) {
548        this.fragmentGroup2.appendChild(row);
549      }
550      this.fragmentGroup2.removeChild(row);
551    }
552    if (clearCollectGroup) {
553      row.collectGroup = undefined;
554    }
555    this.updateGroupDisplay();
556    this.resizeHeight();
557    this.scrollTop = 0;
558    this.refreshFavoriteCanvas();
559    row.currentContext = undefined;
560    if (this.collectRowList1.length === 0 && this.collectRowList2.length === 0) {
561      this.style.height = 'auto';
562      this.style.display = 'none';
563      this.manualHeight = 0;
564    }
565  }
566
567  hideCollectArea(): void {
568    if (this.collect1Expand) {
569      this.collectRowList1.forEach((row) => this.fragmentGroup1.appendChild(row));
570    }
571    if (this.collect2Expand) {
572      this.collectRowList2.forEach((row) => this.fragmentGroup2.appendChild(row));
573    }
574    this.groupTitle1!.style.display = 'none';
575    this.groupTitle2!.style.display = 'none';
576    this.resizeHeight();
577  }
578
579  showCollectArea(): void {
580    if (this.collect1Expand) {
581      this.collectEl1?.appendChild(this.fragmentGroup1);
582    }
583    if (this.collect2Expand) {
584      this.collectEl2?.appendChild(this.fragmentGroup2);
585    }
586    this.updateGroupDisplay();
587    this.resizeHeight();
588  }
589
590  updateGroupDisplay(): void {
591    this.groupTitle1!.style.display = this.collectRowList1.length === 0 ? 'none' : 'flex';
592    this.groupTitle2!.style.display = this.collectRowList2.length === 0 ? 'none' : 'flex';
593  }
594
595  hasCollectRow(): boolean {
596    return this.collectRowList2.length > 0 || this.collectRowList1.length > 0;
597  }
598
599  clearRect(): void {
600    this.canvasCtx?.clearRect(0, 0, this.canvas?.clientWidth ?? 0, this.canvas?.clientHeight ?? 0);
601  }
602
603  drawLines(xs: number[] | undefined, color: string): void {
604    drawLines(this.canvasCtx!, xs ?? [], this.clientHeight, color);
605  }
606
607  drawFlagLineSegment(
608    hoverFlag: Flag | undefined | null,
609    selectFlag: Flag | undefined | null,
610    tse: TimerShaftElement
611  ): void {
612    drawFlagLineSegment(
613      this.canvasCtx,
614      hoverFlag,
615      selectFlag,
616      new Rect(0, 0, TraceRow.FRAME_WIDTH, this.canvas?.clientHeight!),
617      tse
618    );
619  }
620
621  drawWakeUp(): void {
622    drawWakeUp(
623      this.canvasCtx,
624      CpuStruct.wakeupBean,
625      TraceRow.range!.startNS,
626      TraceRow.range!.endNS,
627      TraceRow.range!.totalNS,
628      new Rect(0, 0, TraceRow.FRAME_WIDTH, this.canvas?.clientHeight!)
629    );
630  }
631
632  drawWakeUpList(bean: WakeupBean): void {
633    drawWakeUpList(this.canvasCtx, bean, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, {
634      x: 0,
635      y: 0,
636      width: TraceRow.FRAME_WIDTH,
637      height: this.canvas!.clientHeight!,
638    } as Rect);
639  }
640
641  drawLogsLineSegment(bean: Flag | null | undefined, timeShaft: TimerShaftElement): void {
642    drawLogsLineSegment(
643      this.canvasCtx,
644      bean,
645      {
646        x: 0,
647        y: 0,
648        width: TraceRow.FRAME_WIDTH,
649        height: this.canvas!.clientHeight,
650      },
651      timeShaft
652    );
653  }
654
655  drawLinkLines(nodes: PairPoint[][], tse: TimerShaftElement, isFavorite: boolean, favoriteHeight: number): void {
656    drawLinkLines(this.canvasCtx!, nodes, tse, isFavorite, favoriteHeight);
657  }
658
659  refreshFavoriteCanvas(): void {
660    this.canvas!.style.width = `${this.clientWidth - 248}px`;
661    this.canvas!.style.left = `248px`;
662    this.canvas!.width = this.canvas?.clientWidth! * dpr();
663    this.canvas!.height = this.clientHeight * dpr();
664    this.canvas!.getContext('2d')!.scale(dpr(), dpr());
665    window.publish(window.SmartEvent.UI.RefreshCanvas, {});
666  }
667
668  private getHtmlCss(): string {
669    return `<style>
670    :host{
671        display: none;
672        width: 100%;
673        height: auto;
674        overflow-anchor: none;
675        z-index: 3;
676        box-shadow: 0 10px 10px #00000044;
677        position: relative;
678        overflow: auto;
679        overflow-x: hidden;
680        scroll-behavior: smooth;
681    }
682    .root{
683        width: 100%;
684        box-sizing: border-box;
685    }
686    .panel-canvas{
687        position: absolute;
688        top: 0;
689        right: 0;
690        bottom: 0;
691        box-sizing: border-box;
692    }
693    .icon:hover {
694     color:#ecb93f;
695    }
696    .icon {
697        margin-right: 10px;
698        cursor: pointer;
699    }
700    </style>`;
701  }
702
703  initHtml(): string {
704    return `
705 ${this.getHtmlCss()}
706<canvas id="canvas-panel" class="panel-canvas" ondragstart="return false"></canvas>
707<div class="root">
708    <div id="group-1-title" style="background-color: #efefef;padding: 10px;align-items: center">
709        <lit-icon id="group_1_expand" class="icon" name="caret-down" size="19"></lit-icon>
710        <span style="width: 184px;font-size: 10px;color: #898989">G1</span>
711        <lit-icon id="group_1_collect" name="star-fill" style="color: #5291FF;cursor: pointer" size="19"></lit-icon>
712    </div>
713    <div id="collect-group-1"></div>
714    <div id="group-2-title" style="background-color: #efefef;padding: 10px;align-items: center">
715        <lit-icon id="group_2_expand" class="icon" name="caret-down" size="19"></lit-icon>
716        <span style="width: 184px;font-size: 10px;color: #898989">G2</span>
717        <lit-icon id="group_2_collect" name="star-fill" style="color: #f56940;cursor: pointer" size="19"></lit-icon>
718    </div>
719    <div id="collect-group-2"></div>
720</div>
721`;
722  }
723}
724