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.js'; 17import { LitTabs } from '../../../../base-ui/tabs/lit-tabs.js'; 18import { LitTabpane } from '../../../../base-ui/tabs/lit-tabpane.js'; 19import { BoxJumpParam, SelectionParam } from '../../../bean/BoxSelection.js'; 20import { TabPaneCurrentSelection } from '../sheet/TabPaneCurrentSelection.js'; 21import { TabPaneFlag } from '../timer-shaft/TabPaneFlag.js'; 22import { Flag } from '../timer-shaft/Flag.js'; 23import { WakeupBean } from '../../../bean/WakeupBean.js'; 24import { LitIcon } from '../../../../base-ui/icon/LitIcon.js'; 25import { tabConfig } from './TraceSheetConfig.js'; 26import { TabPaneBoxChild } from '../sheet/cpu/TabPaneBoxChild.js'; 27import { CpuStruct } from '../../../database/ui-worker/ProcedureWorkerCPU.js'; 28import { CpuFreqStruct } from '../../../database/ui-worker/ProcedureWorkerFreq.js'; 29import { CpuFreqLimitsStruct } from '../../../database/ui-worker/ProcedureWorkerCpuFreqLimits.js'; 30import { ThreadStruct } from '../../../database/ui-worker/ProcedureWorkerThread.js'; 31import { FuncStruct } from '../../../database/ui-worker/ProcedureWorkerFunc.js'; 32import { ProcessMemStruct } from '../../../database/ui-worker/ProcedureWorkerMem.js'; 33import { CpuStateStruct } from '../../../database/ui-worker/ProcedureWorkerCpuState.js'; 34import { ClockStruct } from '../../../database/ui-worker/ProcedureWorkerClock.js'; 35import { IrqStruct } from '../../../database/ui-worker/ProcedureWorkerIrq.js'; 36import { JankStruct } from '../../../database/ui-worker/ProcedureWorkerJank.js'; 37import { HeapStruct } from '../../../database/ui-worker/ProcedureWorkerHeap.js'; 38import { LitTable } from '../../../../base-ui/table/lit-table.js'; 39import { threadPool } from '../../../database/SqlLite.js'; 40import { HeapSnapshotStruct } from '../../../database/ui-worker/ProcedureWorkerHeapSnapshot.js'; 41import { TabPaneComparison } from '../sheet/snapshot/TabPaneComparison.js'; 42import { TabPaneSummary } from '../sheet/snapshot/TabPaneSummary.js'; 43import { TabPaneNMStatisticAnalysis } from '../sheet/native-memory/TabPaneNMStatisticAnalysis.js'; 44import { TabPaneCurrent } from '../sheet/TabPaneCurrent.js'; 45import { SlicesTime } from '../timer-shaft/SportRuler.js'; 46import { AppStartupStruct } from '../../../database/ui-worker/ProcedureWorkerAppStartup.js'; 47import { SoStruct } from '../../../database/ui-worker/ProcedureWorkerSoInit.js'; 48@element('trace-sheet') 49export class TraceSheet extends BaseElement { 50 private litTabs: LitTabs | undefined | null; 51 private importDiv: HTMLDivElement | undefined | null; 52 private nav: HTMLDivElement | undefined | null; 53 private selection: SelectionParam | undefined | null; 54 private currentPaneID: string = 'current-selection'; 55 private fragment: DocumentFragment | undefined; 56 57 static get observedAttributes() { 58 return ['mode']; 59 } 60 61 buildTabs(litTabs: LitTabs | undefined | null) { 62 this.fragment = document.createDocumentFragment(); 63 Reflect.ownKeys(tabConfig).forEach((key, index) => { 64 let pane = new LitTabpane(); 65 pane.id = key.toString(); 66 pane.className = 'tabHeight'; 67 pane.tab = tabConfig[key].title; 68 pane.hidden = true; 69 pane.key = `${tabConfig[key].key || index}`; 70 let cls = tabConfig[key].type; 71 let node = new cls(); 72 pane.append(node); 73 this.fragment?.appendChild(pane); 74 }); 75 litTabs!.appendChild(this.fragment); 76 } 77 78 displayTab<T>(...names: string[]): T { 79 this.setAttribute('mode', 'max'); 80 this.showUploadSoBt(null); 81 this.shadowRoot 82 ?.querySelectorAll<LitTabpane>('#tabs lit-tabpane') 83 .forEach((it) => (it.hidden = !names.some((k) => k === it.id))); 84 let litTabpane = this.shadowRoot?.querySelector<LitTabpane>(`#tabs lit-tabpane[id='${names[0]}']`); 85 this.shadowRoot?.querySelector<LitTabs>('#tabs')?.activePane(litTabpane!.key); 86 return litTabpane!.children.item(0) as unknown as T; 87 } 88 89 getComponentByID<T>(id: string): T { 90 return this.getPaneByID(id)!.children.item(0) as unknown as T; 91 } 92 93 getPaneByID(id: string): LitTabpane { 94 return this.shadowRoot!.querySelector(`#${id}`)!; 95 } 96 97 initElements(): void { 98 this.litTabs = this.shadowRoot?.querySelector('#tabs'); 99 this.importDiv = this.shadowRoot?.querySelector('#import_div'); 100 this.buildTabs(this.litTabs); 101 let minBtn = this.shadowRoot?.querySelector('#min-btn'); 102 minBtn?.addEventListener('click', () => {}); 103 this.litTabs!.onTabClick = (e: any) => this.loadTabPaneData(e.detail.key); 104 this.litTabs!.addEventListener('close-handler', () => { 105 Reflect.ownKeys(tabConfig) 106 .reverse() 107 .forEach((id) => { 108 let element = tabConfig[id]; 109 let pane = this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`); 110 if (element.require) { 111 pane!.hidden = !element.require(this.selection); 112 } else { 113 pane!.hidden = true; 114 } 115 }); 116 this.litTabs?.activeByKey(`${this.getPaneByID(this.currentPaneID).key}`); 117 }); 118 this.getComponentByID<any>('box-spt')!.addEventListener('row-click', this.rowClickHandler.bind(this)); 119 this.getComponentByID<any>('box-pts')!.addEventListener('row-click', this.rowClickHandler.bind(this)); 120 this.getComponentByID<any>('box-native-statstics')!.addEventListener('row-click', (e: any) => { 121 this.selection!.statisticsSelectData = e.detail; 122 let pane = this.getPaneByID('box-native-memory'); 123 this.litTabs?.activeByKey(pane.key); 124 (pane.children.item(0) as any)!.fromStastics(this.selection); 125 }); 126 this.getComponentByID<any>('box-virtual-memory-statistics')!.addEventListener('row-click', (e: any) => { 127 this.selection!.fileSystemVMData = { path: e.detail.path }; 128 let pane = this.getPaneByID('box-vm-events'); 129 this.litTabs?.activeByKey(pane.key); 130 if (e.detail.path) { 131 (pane.children.item(0) as any)!.fromStastics(this.selection); 132 } 133 }); 134 this.getComponentByID<any>('box-io-tier-statistics')!.addEventListener('row-click', (e: any) => { 135 this.selection!.fileSystemIoData = { path: e.detail.path }; 136 let pane = this.getPaneByID('box-io-events'); 137 this.litTabs?.activeByKey(pane.key); 138 if (e.detail.path) { 139 (pane.children.item(0) as any)!.fromStastics(this.selection); 140 } 141 }); 142 this.getComponentByID<any>('box-file-system-statistics')!.addEventListener('row-click', (e: any) => { 143 this.selection!.fileSystemFsData = e.detail.data; 144 let pane = this.getPaneByID('box-file-system-event'); 145 this.litTabs?.activeByKey(pane.key); 146 if (e.detail.data) { 147 (pane.children.item(0) as any)!.fromStastics(this.selection); 148 } 149 }); 150 } 151 152 connectedCallback() { 153 this.nav = this.shadowRoot?.querySelector('#tabs')?.shadowRoot?.querySelector('.tab-nav-container'); 154 let tabs: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#tabs'); 155 let navRoot: HTMLDivElement | null | undefined = this.shadowRoot 156 ?.querySelector('#tabs') 157 ?.shadowRoot?.querySelector('.nav-root'); 158 let search: HTMLDivElement | undefined | null = document 159 .querySelector('body > sp-application') 160 ?.shadowRoot?.querySelector('div > div.search-container'); 161 let timerShaft: HTMLDivElement | undefined | null = this.parentElement?.querySelector('.timer-shaft'); 162 let spacer: HTMLDivElement | undefined | null = this.parentElement?.querySelector('.spacer'); 163 let rowsPaneEL: HTMLDivElement | undefined | null = this.parentElement?.querySelector('.rows-pane'); 164 165 let borderTop: number = 1; 166 let initialHeight = { tabs: `calc(30vh + 39px)`, node: '30vh' }; 167 this.nav!.onmousedown = (event) => { 168 (window as any).isSheetMove = true; 169 let litTabpane: NodeListOf<HTMLDivElement> | undefined | null = 170 this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane'); 171 let preY = event.pageY; 172 let preHeight = tabs!.offsetHeight; 173 document.onmousemove = function (event) { 174 let moveY: number = preHeight - (event.pageY - preY); 175 litTabpane!.forEach((node: HTMLDivElement) => { 176 if (spacer!.offsetHeight > rowsPaneEL!.offsetHeight) { 177 tabs!.style.height = moveY + 'px'; 178 node!.style.height = moveY - navRoot!.offsetHeight + 'px'; 179 tabsPackUp!.name = 'down'; 180 } else if ( 181 navRoot!.offsetHeight <= moveY && 182 search!.offsetHeight + timerShaft!.offsetHeight + borderTop + spacer!.offsetHeight <= 183 window.innerHeight - moveY 184 ) { 185 tabs!.style.height = moveY + 'px'; 186 node!.style.height = moveY - navRoot!.offsetHeight + 'px'; 187 tabsPackUp!.name = 'down'; 188 } else if (navRoot!.offsetHeight >= moveY) { 189 tabs!.style.height = navRoot!.offsetHeight + 'px'; 190 node!.style.height = '0px'; 191 tabsPackUp!.name = 'up'; 192 } else if ( 193 search!.offsetHeight + timerShaft!.offsetHeight + borderTop + spacer!.offsetHeight >= 194 window.innerHeight - moveY 195 ) { 196 tabs!.style.height = 197 window.innerHeight - 198 search!.offsetHeight - 199 timerShaft!.offsetHeight - 200 borderTop - 201 spacer!.offsetHeight + 202 'px'; 203 node!.style.height = 204 window.innerHeight - 205 search!.offsetHeight - 206 timerShaft!.offsetHeight - 207 navRoot!.offsetHeight - 208 borderTop - 209 spacer!.offsetHeight + 210 'px'; 211 tabsPackUp!.name = 'down'; 212 } 213 }); 214 }; 215 document.onmouseup = function () { 216 setTimeout(() => { 217 (window as any).isSheetMove = false; 218 }, 100); 219 litTabpane!.forEach((node: HTMLDivElement) => { 220 if (node!.style.height !== '0px' && tabs!.style.height != '') { 221 initialHeight.node = node!.style.height; 222 initialHeight.tabs = tabs!.style.height; 223 } 224 }); 225 this.onmousemove = null; 226 this.onmouseup = null; 227 }; 228 }; 229 let tabsOpenUp: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>('#max-btn'); 230 let tabsPackUp: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>('#min-btn'); 231 let importFileBt: HTMLInputElement | undefined | null = 232 this.shadowRoot?.querySelector<HTMLInputElement>('#import-file'); 233 let exportDataBt: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>('#export-btn'); 234 tabsOpenUp!.onclick = () => { 235 tabs!.style.height = window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - borderTop + 'px'; 236 let litTabpane: NodeListOf<HTMLDivElement> | undefined | null = 237 this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane'); 238 litTabpane!.forEach((node: HTMLDivElement) => { 239 node!.style.height = 240 window.innerHeight - 241 search!.offsetHeight - 242 timerShaft!.offsetHeight - 243 navRoot!.offsetHeight - 244 borderTop + 245 'px'; 246 initialHeight.node = node!.style.height; 247 }); 248 initialHeight.tabs = tabs!.style.height; 249 tabsPackUp!.name = 'down'; 250 }; 251 tabsPackUp!.onclick = () => { 252 let litTabpane: NodeListOf<HTMLDivElement> | undefined | null = 253 this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane'); 254 if (tabsPackUp!.name == 'down') { 255 tabs!.style.height = navRoot!.offsetHeight + 'px'; 256 litTabpane!.forEach((node: HTMLDivElement) => (node!.style.height = '0px')); 257 tabsPackUp!.name = 'up'; 258 (window as any).isPackUpTable = true; 259 } else { 260 tabsPackUp!.name = 'down'; 261 tabs!.style.height = initialHeight.tabs; 262 litTabpane!.forEach((node: HTMLDivElement) => (node!.style.height = initialHeight.node)); 263 } 264 }; 265 importFileBt!.addEventListener('change', (event) => { 266 let files = importFileBt?.files; 267 if (files) { 268 let fileList: Array<File> = []; 269 for (let file of files) { 270 if (file.name.endsWith('.so')) { 271 fileList.push(file); 272 } 273 } 274 if (fileList.length > 0) { 275 importFileBt!.disabled = true; 276 window.publish(window.SmartEvent.UI.Loading, true); 277 threadPool.submit( 278 'upload-so', 279 '', 280 fileList, 281 (res: string) => { 282 importFileBt!.disabled = false; 283 if (res === 'ok') { 284 window.publish(window.SmartEvent.UI.UploadSOFile, {}); 285 } else { 286 window.publish(window.SmartEvent.UI.Error, 'parse so file failed!'); 287 } 288 }, 289 'upload-so' 290 ); 291 } 292 fileList.length = 0; 293 } 294 importFileBt!.files = null; 295 importFileBt!.value = ''; 296 }); 297 exportDataBt!.onclick = () => { 298 let currentTab = this.getTabpaneByKey(this.litTabs?.activekey!); 299 if (currentTab) { 300 let tables = Array.from( 301 (currentTab.firstChild as BaseElement).shadowRoot?.querySelectorAll<LitTable>('lit-table') || [] 302 ); 303 for (let table of tables) { 304 if (!table.hasAttribute('hideDownload')) { 305 table.exportData(); 306 } 307 } 308 } 309 }; 310 } 311 312 getTabpaneByKey(key: string): LitTabpane | undefined { 313 let tabs = Array.from(this.shadowRoot?.querySelectorAll<LitTabpane>('#tabs lit-tabpane').values() || []); 314 return tabs.find((it) => it.key === key); 315 } 316 317 initHtml(): string { 318 return ` 319 <style> 320 :host([mode='hidden']){ 321 display: none; 322 } 323 :host{ 324 display: block; 325 background-color: rebeccapurple; 326 } 327 .tabHeight{ 328 height: 30vh; 329 background-color: var(--dark-background,#FFFFFF); 330 } 331 </style> 332 <div id="container" style="border-top: 1px solid var(--dark-border1,#D5D5D5);"> 333 <lit-tabs id="tabs" position="top-left" activekey="1" mode="card" > 334 <div slot="right" style="margin: 0 10px; color: var(--dark-icon,#606060);display: flex;align-items: center;"> 335 <div title="SO导入" id="import_div" style="width: 20px;height: 20px;display: flex;flex-direction: row;margin-right: 10px"> 336 <input id="import-file" style="display: none;pointer-events: none" type="file" webkitdirectory> 337 <label style="width: 20px;height: 20px;cursor: pointer;" for="import-file"> 338 <lit-icon id="import-btn" name="copy-csv" style="pointer-events: none" size="20"> 339 </lit-icon> 340 </label> 341 </div> 342 <lit-icon title="下载数据" id="export-btn" name="import-so" style="font-weight: bold;cursor: pointer;margin-right: 10px" size="20"> 343 </lit-icon> 344 <lit-icon title="最大化" id="max-btn" name="vertical-align-top" style="font-weight: bold;cursor: pointer;margin-right: 10px" size="20"> 345 </lit-icon> 346 <lit-icon title="最小化" id="min-btn" name="down" style="font-weight: bold;cursor: pointer;" size="20"> 347 </lit-icon> 348 </div> 349 </lit-tabs> 350 </div>`; 351 } 352 displayCurrent = (data: SlicesTime) => 353 this.displayTab<TabPaneCurrent>('tabpane-current').setCurrentSlicesTime(data); 354 displayThreadData = ( 355 data: ThreadStruct, 356 scrollCallback: ((e: ThreadStruct) => void) | undefined, 357 scrollWakeUp: (d: any) => void | undefined 358 ) => this.displayTab<TabPaneCurrentSelection>('current-selection').setThreadData(data, scrollCallback, scrollWakeUp); 359 displayMemData = (data: ProcessMemStruct) => 360 this.displayTab<TabPaneCurrentSelection>('current-selection').setMemData(data); 361 displayClockData = (data: ClockStruct) => 362 this.displayTab<TabPaneCurrentSelection>('current-selection').setClockData(data); 363 displayIrqData = (data: IrqStruct) => this.displayTab<TabPaneCurrentSelection>('current-selection').setIrqData(data); 364 displayStartupData = (data: AppStartupStruct, scrollCallback: Function) => 365 this.displayTab<TabPaneCurrentSelection>('current-selection').setStartupData(data,scrollCallback); 366 displayStaticInitData = (data: SoStruct, scrollCallback: Function) => 367 this.displayTab<TabPaneCurrentSelection>('current-selection').setStaticInitData(data,scrollCallback); 368 369 displayNativeHookData = (data: HeapStruct, rowType: string) => { 370 let val = new SelectionParam(); 371 val.nativeMemoryStatistic.push(rowType); 372 val.nativeMemory = []; 373 val.leftNs = data.startTime!; 374 val.rightNs = data.startTime! + data.dur! - 1; 375 this.selection = val; 376 this.displayTab<TabPaneNMStatisticAnalysis>('box-native-statistic-analysis', 'box-native-calltree').data = val; 377 this.showUploadSoBt(val); 378 }; 379 380 displayFuncData = (names: string[], data: FuncStruct, scrollCallback: Function) => 381 this.displayTab<TabPaneCurrentSelection>(...names).setFunctionData(data, scrollCallback); 382 displayCpuData = ( 383 data: CpuStruct, 384 callback: ((data: WakeupBean | null) => void) | undefined = undefined, 385 scrollCallback?: (data: CpuStruct) => void 386 ) => this.displayTab<TabPaneCurrentSelection>('current-selection').setCpuData(data, callback, scrollCallback); 387 displayJankData = ( 388 data: JankStruct, 389 callback: ((data: Array<any>) => void) | undefined = undefined, 390 scrollCallback: ((e: JankStruct) => void) | undefined 391 ) => this.displayTab<TabPaneCurrentSelection>('current-selection').setJankData(data, callback, scrollCallback); 392 displaySnapshotData = ( 393 data: HeapSnapshotStruct, 394 dataList: Array<HeapSnapshotStruct>, 395 scrollCallback?: (data: HeapSnapshotStruct, dataList: Array<HeapSnapshotStruct>) => void 396 ) => { 397 if (dataList.length > 1) { 398 this.displayTab<TabPaneSummary>('box-heap-summary', 'box-heap-comparison').setSnapshotData( 399 data, 400 dataList, 401 scrollCallback 402 ); 403 let nav = this.shadowRoot!.querySelector('#tabs')!.shadowRoot!.querySelector( 404 '#nav > #nav-comparison' 405 ) as HTMLDivElement; 406 let tabPaneComparison = this.shadowRoot!.querySelector( 407 '#box-heap-comparison > tabpane-comparison' 408 ) as TabPaneComparison; 409 nav!.onclick = () => { 410 tabPaneComparison.initComparison(data, dataList); 411 }; 412 } else { 413 this.displayTab<TabPaneSummary>('box-heap-summary').setSnapshotData(data, dataList, scrollCallback); 414 } 415 }; 416 displayFlagData = (flagObj: Flag) => this.displayTab<TabPaneFlag>('box-flag').setFlagObj(flagObj); 417 displayFreqData = () => 418 (this.displayTab<TabPaneCurrentSelection>('box-freq').data = CpuFreqStruct.selectCpuFreqStruct); 419 displayCpuStateData = () => 420 (this.displayTab<TabPaneCurrentSelection>('cpu-state-click').data = CpuStateStruct.selectStateStruct); 421 displayFreqLimitData = () => 422 (this.displayTab<TabPaneCurrentSelection>('box-freq-limit').data = CpuFreqLimitsStruct.selectCpuFreqLimitsStruct); 423 424 rangeSelect(selection: SelectionParam, restore = false): boolean { 425 this.selection = selection; 426 this.showUploadSoBt(selection); 427 Reflect.ownKeys(tabConfig) 428 .reverse() 429 .forEach((id) => { 430 let element = tabConfig[id]; 431 if (element.require) { 432 if (element.require(selection)) { 433 let pane = this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`); 434 pane!.hidden = false; 435 } else { 436 this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`)!.hidden = true; 437 } 438 } else { 439 this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`)!.hidden = true; 440 } 441 }); 442 if (restore) { 443 if (this.litTabs?.activekey) { 444 this.loadTabPaneData(this.litTabs?.activekey); 445 this.setAttribute('mode', 'max'); 446 return true; 447 } else { 448 this.setAttribute('mode', 'hidden'); 449 return false; 450 } 451 } else { 452 let firstPane = this.shadowRoot!.querySelector<LitTabpane>(`lit-tabpane[hidden='false']`); 453 if (firstPane) { 454 this.litTabs?.activeByKey(firstPane.key); 455 this.loadTabPaneData(firstPane.key); 456 this.setAttribute('mode', 'max'); 457 return true; 458 } else { 459 this.setAttribute('mode', 'hidden'); 460 return false; 461 } 462 } 463 } 464 465 updateRangeSelect(): boolean { 466 if ( 467 this.selection && 468 (this.selection.nativeMemory.length > 0 || 469 this.selection.nativeMemoryStatistic.length > 0 || 470 this.selection.perfSampleIds.length > 0 || 471 this.selection.fileSystemType.length > 0 || 472 this.selection.fsCount > 0 || 473 this.selection.fileSysVirtualMemory || 474 this.selection.vmCount > 0 || 475 this.selection.diskIOLatency || 476 this.selection.diskIOipids.length > 0) 477 ) { 478 let param: SelectionParam = new SelectionParam(); 479 Object.assign(param, this.selection); 480 this.rangeSelect(param, true); 481 return true; 482 } else { 483 return false; 484 } 485 } 486 487 showUploadSoBt(selection: SelectionParam | null | undefined) { 488 if ( 489 selection && 490 (selection.nativeMemory.length > 0 || 491 selection.nativeMemoryStatistic.length > 0 || 492 selection.perfSampleIds.length > 0 || 493 selection.fileSystemType.length > 0 || 494 selection.fsCount > 0 || 495 selection.fileSysVirtualMemory || 496 selection.vmCount > 0 || 497 selection.diskIOLatency || 498 selection.diskIOipids.length > 0) 499 ) { 500 this.importDiv!.style.display = 'flex'; 501 } else { 502 this.importDiv!.style.display = 'none'; 503 } 504 } 505 506 loadTabPaneData(key: string) { 507 let component: any = this.shadowRoot 508 ?.querySelector<LitTabpane>(`#tabs lit-tabpane[key='${key}']`) 509 ?.children.item(0); 510 if (component) { 511 component.data = this.selection; 512 } 513 } 514 515 rowClickHandler(e: any) { 516 this.currentPaneID = e.target.parentElement.id; 517 this.shadowRoot!.querySelectorAll<LitTabpane>(`lit-tabpane`).forEach((it) => 518 it.id != this.currentPaneID ? (it.hidden = true) : (it.hidden = false) 519 ); 520 let pane = this.getPaneByID('box-cpu-child'); 521 pane.closeable = true; 522 pane.hidden = false; 523 this.litTabs!.activeByKey(pane.key); 524 pane.tab = e.detail.title; 525 let param = new BoxJumpParam(); 526 param.leftNs = this.selection!.leftNs; 527 param.rightNs = this.selection!.rightNs; 528 param.state = e.detail.state; 529 param.threadId = e.detail.threadId; 530 param.processId = e.detail.processId; 531 (pane.children.item(0) as TabPaneBoxChild).data = param; 532 } 533 534 clearMemory() { 535 let allTabs = Array.from(this.shadowRoot?.querySelectorAll<LitTabpane>('#tabs lit-tabpane').values() || []); 536 allTabs.forEach(tab => { 537 if (tab) { 538 let tables = Array.from( 539 (tab.firstChild as BaseElement).shadowRoot?.querySelectorAll<LitTable>('lit-table') || [] 540 ); 541 for (let table of tables) { 542 table.recycleDataSource = []; 543 } 544 } 545 }); 546 } 547} 548