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