diff --git a/ide/src/base-ui/menu/LitMainMenu.ts b/ide/src/base-ui/menu/LitMainMenu.ts index 2cf5de8d4d42b7ebc21c1b01752f4b1a37459c30..19d7aa5e12ac2191ab53b8503d67675b4827d969 100644 --- a/ide/src/base-ui/menu/LitMainMenu.ts +++ b/ide/src/base-ui/menu/LitMainMenu.ts @@ -18,7 +18,6 @@ import './LitMainMenuItem.js'; import './LitMainMenuGroup.js'; import { LitMainMenuGroup } from './LitMainMenuGroup.js'; import { LitMainMenuItem } from './LitMainMenuItem.js'; -let backgroundColor = sessionStorage.getItem('backgroundColor'); @element('lit-main-menu') export class LitMainMenu extends BaseElement { @@ -37,6 +36,11 @@ export class LitMainMenu extends BaseElement { this._menus = value; this.shadowRoot?.querySelectorAll('lit-main-menu-group').forEach((a) => a.remove()); let menuBody = this.shadowRoot?.querySelector('.menu-body'); + if (this.getAttribute('main_menu') === '1' && window.localStorage.getItem('Theme') == 'dark') { + this.style.backgroundColor = '#262f3c'; + } else { + this.style.backgroundColor = '#fff'; + } value?.forEach((it) => { let group = new LitMainMenuGroup(); group.setAttribute('title', it.title || ''); @@ -46,11 +50,22 @@ export class LitMainMenu extends BaseElement { } else { group.removeAttribute('collapsed'); } + let groupName = group!.shadowRoot!.querySelector('.group-name') as LitMainMenuGroup; + let groupDescribe = group!.shadowRoot!.querySelector('.group-describe') as LitMainMenuGroup; menuBody?.appendChild(group); it.children?.forEach((item: any) => { let th = new LitMainMenuItem(); th.setAttribute('icon', item.icon || ''); th.setAttribute('title', item.title || ''); + if (this.getAttribute('main_menu') === '1' && window.localStorage.getItem('Theme') === 'dark') { + groupName.style.color = 'white'; + groupDescribe.style.color = 'white'; + th!.style.color = 'white'; + } else { + groupName.style.color = 'black'; + groupDescribe.style.color = 'black'; + th!.style.color = 'black'; + } if (item.fileChoose) { th.setAttribute('file', ''); th.addEventListener('file-change', (e) => { @@ -94,7 +109,7 @@ export class LitMainMenu extends BaseElement { height: 100vh; display: flex; flex-direction: column; - background-color: ${backgroundColor}; + background-color: #fff; } .menu-body ::-webkit-scrollbar-thumb { @@ -138,10 +153,10 @@ export class LitMainMenu extends BaseElement { color: #94979d; font-size: 0.6rem; } - .color{ + .color, .customColor{ cursor: pointer; font-size: 0.6rem; - padding: 20px; + padding: 20px 0px 20px 20px; } *{ box-sizing: border-box; @@ -164,9 +179,9 @@ export class LitMainMenu extends BaseElement { -
-
- +
+
+
diff --git a/ide/src/base-ui/menu/LitMainMenuGroup.ts b/ide/src/base-ui/menu/LitMainMenuGroup.ts index 069c322b94c3fc21be09a113e74c15e80cb4a457..884fad542a26d94288d19262a1f0dee302e8c7e0 100644 --- a/ide/src/base-ui/menu/LitMainMenuGroup.ts +++ b/ide/src/base-ui/menu/LitMainMenuGroup.ts @@ -14,7 +14,6 @@ */ import { BaseElement, element } from '../BaseElement.js'; -let textColor = ''; @element('lit-main-menu-group') export class LitMainMenuGroup extends BaseElement { @@ -65,16 +64,6 @@ export class LitMainMenuGroup extends BaseElement { } this.collapsed = !this.collapsed; }); - let backgroundColor = sessionStorage.getItem('backgroundColor'); - if (backgroundColor == 'rgb(38, 47, 60)') { - textColor = 'white'; - this.groupNameEl!.style.color = 'white'; - this.groupDescEl!.style.color = 'white'; - } else { - textColor = 'black'; - this.groupNameEl!.style.color = 'black'; - this.groupDescEl!.style.color = 'black'; - } } initHtml(): string { @@ -121,18 +110,17 @@ export class LitMainMenuGroup extends BaseElement { .group-name{ font-size: 14px; font-family: Helvetica; - color: ${textColor}; + color: #000; padding: 20px 24px 0px 24px; line-height: 16px; font-weight: 400; text-align: left; } .group-describe{ - color: ${textColor}; + color: #000; font-size: 0.6rem; padding: 4px 24px 20px 24px; } -
diff --git a/ide/src/base-ui/menu/LitMainMenuItem.ts b/ide/src/base-ui/menu/LitMainMenuItem.ts index cbe466bb597d554f047bb1ba3b4915cf8f382956..cb849d81e18b3598c37de58d0c1a79a0577d25f2 100644 --- a/ide/src/base-ui/menu/LitMainMenuItem.ts +++ b/ide/src/base-ui/menu/LitMainMenuItem.ts @@ -14,7 +14,6 @@ */ import { BaseElement, element } from '../BaseElement.js'; -let textColor = ''; @element('lit-main-menu-item') export class LitMainMenuItem extends BaseElement { @@ -66,14 +65,6 @@ export class LitMainMenuItem extends BaseElement { this.titleEl = this.shadowRoot?.querySelector('.name'); this.iconEl = this.shadowRoot?.querySelector('.icon'); this.fileEL = this.shadowRoot?.querySelector('.file'); - let backgroundColor = sessionStorage.getItem('backgroundColor'); - if (backgroundColor == 'rgb(38, 47, 60)') { - textColor = 'white'; - this.style.color = 'white'; - } else { - textColor = 'black'; - this.style.color = 'black'; - } } isFile(): boolean { @@ -116,7 +107,7 @@ export class LitMainMenuItem extends BaseElement { display: flex; font-family: Helvetica; font-size: 14px; - color: ${textColor}; + color: #000; text-align: left; line-height: 20px; font-weight: 400 diff --git a/ide/src/base-ui/radiobox/LitRadioBox.ts b/ide/src/base-ui/radiobox/LitRadioBox.ts index 072669120a947e4b5b5da8784125ae291b59f2fa..92067fa3aa5cda5c2cda1cd2794a506bc0d0c48e 100644 --- a/ide/src/base-ui/radiobox/LitRadioBox.ts +++ b/ide/src/base-ui/radiobox/LitRadioBox.ts @@ -85,7 +85,7 @@ export class LitRadioBox extends BaseElement { position:absolute; clip:rect(0,0,0,0); } - :host([dis=round]) :host(:focus-within) .selected label:hover .selected{ + :host([dis=round]) :host(:focus-within) .selected label:hover .selected{ z-index:1; border-color:#a671ef; } @@ -119,6 +119,9 @@ export class LitRadioBox extends BaseElement { background:#a671ef; transform: scale(0); } + :host([dis=round]) .blue::before{ + background: #0a59f7; + } :host([dis=round]) #radio:focus-visible+label .selected::after{ transform:scale(2.5); } @@ -128,7 +131,10 @@ export class LitRadioBox extends BaseElement { :host([dis=round]) #radio:checked+label .selected{ border-color:#a671ef; } - :host([dis=check]):host{ + :host([dis=round]) #radio:checked+label .blue{ + border-color: #0a59f7; + } + :host([dis=check]):host{ opacity: 0.9; font-family: Helvetica,serif; font-size: 14px; diff --git a/ide/src/base-ui/select/LitAllocationSelect.ts b/ide/src/base-ui/select/LitAllocationSelect.ts index 1d595873933ce379b4b7f652f2dc4a781b567e95..de3cd0b4d3a1cae3b719297ba44a6ea16457e25c 100644 --- a/ide/src/base-ui/select/LitAllocationSelect.ts +++ b/ide/src/base-ui/select/LitAllocationSelect.ts @@ -211,7 +211,7 @@ export class LitAllocationSelect extends BaseElement { initData() { this.selectAllocationInputEl = this.shadowRoot!.querySelector('input'); this.selectAllocationOptions = this.shadowRoot!.querySelector('.body') as HTMLDivElement; - this.selectAllocationInputEl?.addEventListener('keyup', () => { + this.selectAllocationInputEl?.addEventListener('input', () => { let filter = [...this.shadowRoot!.querySelectorAll('.option')].filter((a: HTMLDivElement) => { if (a.textContent!.indexOf(this.selectAllocationInputEl!.value) <= -1) { a.style.display = 'none'; diff --git a/ide/src/base-ui/slider/LitSlider.ts b/ide/src/base-ui/slider/LitSlider.ts index 3914c84606eadf50c34fa321cbfc0159eadb2e84..060e6812b87832aa102e07a084f4874a5fa936f4 100644 --- a/ide/src/base-ui/slider/LitSlider.ts +++ b/ide/src/base-ui/slider/LitSlider.ts @@ -26,7 +26,7 @@ export class LitSlider extends BaseElement { private defaultTimeText: string | undefined | null; static get observedAttributes() { - return ['percent', 'disabled-X', 'custom-slider', 'custom-line', 'custom-button']; + return ['percent', 'disabled-X', 'custom-slider', 'custom-line', 'custom-button', 'disabled']; } get sliderStyle(): LitSliderStyle { @@ -45,6 +45,18 @@ export class LitSlider extends BaseElement { } } + get disabled() { + return this.getAttribute('disabled') !== null; + } + + set disabled(value) { + if (value === null || value === false) { + this.removeAttribute('disabled'); + } else { + this.setAttribute('disabled', ''); + } + } + set sliderStyle(value: LitSliderStyle) { this.litSliderStyle = value; this.currentValue = Number(value.defaultValue); @@ -238,6 +250,9 @@ export class LitSlider extends BaseElement { z-index:10 } + :host([disabled]) #slider{ + opacity:0.6; + }
diff --git a/ide/src/base-ui/table/LitPageTable.ts b/ide/src/base-ui/table/LitPageTable.ts index 084a1694c93a475c5d60614b97e93186857fdcbc..f661f1da3aa02888c0cba17ea45b8a3f500f62a7 100644 --- a/ide/src/base-ui/table/LitPageTable.ts +++ b/ide/src/base-ui/table/LitPageTable.ts @@ -31,7 +31,7 @@ export class LitPageTable extends BaseElement { public itemTextHandleMap: Map string> = new Map string>(); private ds: Array = []; public recycleDs: Array = []; - private gridTemplateColumns: any; + private gridTemplateColumns: Array = []; private st: HTMLSlotElement | null | undefined; private tableElement: HTMLDivElement | null | undefined; private exportProgress: LitProgressBar | null | undefined; @@ -233,6 +233,11 @@ export class LitPageTable extends BaseElement { height: auto; cursor: pointer; } + .td label{ + overflow: hidden; + text-overflow: ellipsis; + white-space: normal; + } .td text{ overflow: hidden; text-overflow: ellipsis; @@ -391,6 +396,14 @@ export class LitPageTable extends BaseElement { bottom:20px; z-index: 999999; } + .resize{ + width: 2px; + margin-right: 3px; + height: 20px; + background-color: #e0e0e0; + cursor: col-resize; + } + .progress{ position: absolute; height: 1px; @@ -554,8 +567,8 @@ export class LitPageTable extends BaseElement { box.appendChild(checkbox); rowElement.appendChild(box); } - let area: Array = [], - gridTemplateColumns: Array = []; + let area: Array = []; + this.gridTemplateColumns = []; let resolvingArea = (columns: any, x: any, y: any) => { columns.forEach((a: any, i: any) => { if (!area[y]) area[y] = []; @@ -585,6 +598,12 @@ export class LitPageTable extends BaseElement { x++; let h: any = document.createElement('div'); h.classList.add('td'); + if (i > 0) { + let resizeDiv: HTMLDivElement = document.createElement('div'); + resizeDiv.classList.add('resize'); + h.appendChild(resizeDiv); + this.resizeEventHandler(rowElement, resizeDiv, i); + } if (a.hasAttribute('order')) { h.sortType = 0; h.classList.add('td-order'); @@ -622,6 +641,9 @@ export class LitPageTable extends BaseElement { h.appendChild(upSvg); h.appendChild(downSvg); h.onclick = () => { + if (this.isResize || this.resizeColumnIndex !== -1) { + return; + } this?.shadowRoot?.querySelectorAll('.td-order svg').forEach((it: any) => { it.setAttribute('fill', 'let(--dark-color1,#212121)'); it.sortType = 0; @@ -668,7 +690,7 @@ export class LitPageTable extends BaseElement { }; } h.style.justifyContent = a.getAttribute('align'); - gridTemplateColumns.push(a.getAttribute('width') || '1fr'); + this.gridTemplateColumns.push(a.getAttribute('width') || '1fr'); h.style.gridArea = key; let titleLabel = document.createElement('label'); titleLabel.textContent = a.title; @@ -686,15 +708,14 @@ export class LitPageTable extends BaseElement { if (!rows[i]) rows[i] = array[j - 1][i]; } }); - this.gridTemplateColumns = gridTemplateColumns.join(' '); if (this.selectable) { let s = area.map((a) => '"_checkbox_ ' + a.map((aa: any) => aa.t).join(' ') + '"').join(' '); - rowElement.style.gridTemplateColumns = '60px ' + gridTemplateColumns.join(' '); + rowElement.style.gridTemplateColumns = '60px ' + this.gridTemplateColumns.join(' '); rowElement.style.gridTemplateRows = `repeat(${area.length},1fr)`; rowElement.style.gridTemplateAreas = s; } else { let s = area.map((a) => '"' + a.map((aa: any) => aa.t).join(' ') + '"').join(' '); - rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); + rowElement.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); rowElement.style.gridTemplateRows = `repeat(${area.length},1fr)`; rowElement.style.gridTemplateAreas = s; } @@ -703,11 +724,75 @@ export class LitPageTable extends BaseElement { this.treeElement!.style.top = this.theadElement?.clientHeight + 'px'; }); }); - this.shadowRoot!.addEventListener('load', function (event) {}); this.tableElement!.addEventListener('mouseout', (ev) => this.mouseOut()); } + private isResize: boolean = false; + private resizeColumnIndex: number = -1; + private resizeDownX: number = 0; + private columnMinWidth: number = 50; + private beforeResizeWidth1: number = 0; + private beforeResizeWidth2: number = 0; + resizeEventHandler(header: HTMLDivElement, element: HTMLDivElement, index: number){ + header.addEventListener('mousemove', (event) => { + if (this.isResize) { + let width = event.clientX - this.resizeDownX; + header.style.cursor = 'col-resize'; + let preWidth = this.beforeResizeWidth1, nowWidth = this.beforeResizeWidth2; + if (width < 0) { + preWidth = Math.max(this.beforeResizeWidth1 + width, this.columnMinWidth); + nowWidth = (this.beforeResizeWidth1 - preWidth) + this.beforeResizeWidth2; + } + if (width > 0) { + nowWidth = Math.max(this.beforeResizeWidth2 - width, this.columnMinWidth); + preWidth = (this.beforeResizeWidth2 - nowWidth) + this.beforeResizeWidth1; + } + this.gridTemplateColumns[this.resizeColumnIndex - 1] = `${preWidth}px`; + this.gridTemplateColumns[this.resizeColumnIndex] = `${nowWidth}px`; + header.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); + this.shadowRoot!.querySelectorAll('.tr').forEach((tr) => { + tr.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); + }); + event.preventDefault(); + event.stopPropagation(); + } else { + header.style.cursor = 'pointer'; + } + }); + header.addEventListener('mouseup', (event) => { + this.isResize = false; + this.resizeDownX = 0; + header.style.cursor = 'pointer'; + setTimeout(() => { + this.resizeColumnIndex = -1; + }, 100); + event.stopPropagation(); + event.preventDefault(); + }); + header.addEventListener('mouseleave', (event) => { + event.stopPropagation(); + event.preventDefault(); + this.isResize = false; + this.resizeDownX = 0; + this.resizeColumnIndex = -1; + header.style.cursor = 'pointer'; + }); + element.addEventListener('mousedown', (event)=>{ + this.isResize = true; + this.resizeColumnIndex = index; + this.resizeDownX = event.clientX; + let pre = (header.childNodes.item(this.resizeColumnIndex - 1) as HTMLDivElement); + let now = (header.childNodes.item(this.resizeColumnIndex) as HTMLDivElement); + this.beforeResizeWidth1 = pre.clientWidth; + this.beforeResizeWidth2 = now.clientWidth; + event.stopPropagation(); + }); + element.addEventListener('click',(event) => { + event.stopPropagation(); + }); + } + // Is called when the custom element is removed from the document DOM. disconnectedCallback() {} @@ -918,7 +1003,6 @@ export class LitPageTable extends BaseElement { createNewTreeTableElement(rowData: TableRowObject): any { let newTableElement = document.createElement('div'); newTableElement.classList.add('tr'); - let gridTemplateColumns: Array = []; let treeTop = 0; if (this.treeElement!.children?.length > 0) { let transX = Number((this.treeElement?.lastChild as HTMLElement).style.transform.replace(/[^0-9]/gi, '')); @@ -927,16 +1011,17 @@ export class LitPageTable extends BaseElement { this?.columns?.forEach((column: any, index) => { let dataIndex = column.getAttribute('data-index') || '1'; let td: any; + let text = this.formatName(dataIndex, rowData.data[dataIndex]); if (index === 0) { if (column.template) { td = column.template.render(rowData.data).content.cloneNode(true); td.template = column.template; - td.title = rowData.data[dataIndex]; + td.title = text; } else { td = document.createElement('div'); - td.innerHTML = this.formatName(dataIndex, rowData.data[dataIndex]); + td.innerHTML = text; td.dataIndex = dataIndex; - td.title = rowData.data[dataIndex]; + td.title = text; } if (rowData.data.children && rowData.data.children.length > 0 && !rowData.data.hasNext) { let btn = this.createExpandBtn(rowData); @@ -980,20 +1065,19 @@ export class LitPageTable extends BaseElement { this.treeElement?.append(td); this.currentTreeDivList.push(td); } else { - gridTemplateColumns.push(column.getAttribute('width') || '1fr'); td = document.createElement('div'); td.classList.add('td'); td.style.overflow = 'hidden'; td.style.textOverflow = 'ellipsis'; td.style.whiteSpace = 'nowrap'; - td.title = rowData.data[dataIndex]; + td.title = text; td.dataIndex = dataIndex; td.style.justifyContent = column.getAttribute('align') || 'flex-start'; if (column.template) { td.appendChild(column.template.render(rowData.data).content.cloneNode(true)); td.template = column.template; } else { - td.innerHTML = this.formatName(dataIndex, rowData.data[dataIndex]); + td.innerHTML = text; } newTableElement.append(td); } @@ -1003,7 +1087,7 @@ export class LitPageTable extends BaseElement { lastChild.style.transform = `translateY(${treeTop}px)`; } (newTableElement as any).data = rowData.data; - newTableElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); + newTableElement.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); newTableElement.style.position = 'absolute'; newTableElement.style.top = '0px'; newTableElement.style.left = '0px'; @@ -1172,10 +1256,8 @@ export class LitPageTable extends BaseElement { createNewTableElement(rowData: any): any { let newTableElement = document.createElement('div'); newTableElement.classList.add('tr'); - let gridTemplateColumns: Array = []; this?.columns?.forEach((column: any) => { let dataIndex = column.getAttribute('data-index') || '1'; - gridTemplateColumns.push(column.getAttribute('width') || '1fr'); let td: any; td = document.createElement('div'); td.classList.add('td'); @@ -1184,12 +1266,13 @@ export class LitPageTable extends BaseElement { td.style.whiteSpace = 'nowrap'; td.dataIndex = dataIndex; td.style.justifyContent = column.getAttribute('align') || 'flex-start'; - td.title = rowData.data[dataIndex]; + let text = this.formatName(dataIndex, rowData.data[dataIndex]); + td.title = text; if (column.template) { td.appendChild(column.template.render(rowData.data).content.cloneNode(true)); td.template = column.template; } else { - td.innerHTML = this.formatName(dataIndex, rowData.data[dataIndex]); + td.innerHTML = text; } newTableElement.append(td); }); @@ -1204,7 +1287,7 @@ export class LitPageTable extends BaseElement { } (newTableElement as any).data = rowData.data; newTableElement.style.cursor = 'pointer'; - newTableElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); + newTableElement.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); newTableElement.style.position = 'absolute'; newTableElement.style.top = '0px'; newTableElement.style.left = '0px'; @@ -1237,8 +1320,9 @@ export class LitPageTable extends BaseElement { .content.cloneNode(true).innerHTML; } else { let dataIndex = this.columns![0].getAttribute('data-index') || '1'; - firstElement.innerHTML = this.formatName(dataIndex, rowObject.data[dataIndex]); - firstElement.title = rowObject.data[dataIndex]; + let text = this.formatName(dataIndex, rowObject.data[dataIndex]); + firstElement.innerHTML = text; + firstElement.title = text; } if (rowObject.children && rowObject.children.length > 0 && !rowObject.data.hasNext) { let btn = this.createExpandBtn(rowObject); @@ -1265,15 +1349,16 @@ export class LitPageTable extends BaseElement { } } let dataIndex = this.columns![idx].getAttribute('data-index') || '1'; + let text = this.formatName(dataIndex, rowObject.data[dataIndex]); if ((this.columns![idx] as any).template) { (child as HTMLElement).innerHTML = ''; (child as HTMLElement).appendChild( (this.columns![idx] as any).template.render(rowObject.data).content.cloneNode(true) ); - (child as HTMLElement).title = rowObject.data[dataIndex]; + (child as HTMLElement).title = text; } else { - (child as HTMLElement).innerHTML = this.formatName(dataIndex, rowObject.data[dataIndex]); - (child as HTMLElement).title = rowObject.data[dataIndex]; + (child as HTMLElement).innerHTML = text; + (child as HTMLElement).title = text; } }); if (element.style.display == 'none') { diff --git a/ide/src/base-ui/table/lit-table.ts b/ide/src/base-ui/table/lit-table.ts index c471d3823aa5b5e7a9a370fa208fbb22b7661f5a..56c646712fa49c66d13bfe258d6eb54aa3290e16 100644 --- a/ide/src/base-ui/table/lit-table.ts +++ b/ide/src/base-ui/table/lit-table.ts @@ -35,7 +35,7 @@ export class LitTable extends HTMLElement { private ds: Array = []; public recycleDs: Array = []; private normalDs: Array = []; - private gridTemplateColumns: any; + private gridTemplateColumns: Array = []; /*Grid css layout descriptions are obtained according to the clustern[] nested structure*/ private st: HTMLSlotElement | null | undefined; private tableElement: HTMLDivElement | null | undefined; @@ -53,6 +53,7 @@ export class LitTable extends HTMLElement { private _loading: boolean = false; private value: any; private _mode = TableMode.Expand; + private columnResizeEnable: boolean = true; constructor() { super(); @@ -96,6 +97,11 @@ export class LitTable extends HTMLElement { height: auto; cursor: pointer; } + .td label{ + overflow: hidden; + text-overflow: ellipsis; + white-space: normal; + } .td text{ overflow: hidden; text-overflow: ellipsis; @@ -237,6 +243,13 @@ export class LitTable extends HTMLElement { bottom:20px; z-index: 999999; } + .resize{ + width: 2px; + margin-right: 3px; + height: 20px; + background-color: #e0e0e0; + cursor: col-resize; + } .progress{ position: absolute; height: 1px; @@ -324,13 +337,15 @@ export class LitTable extends HTMLElement { } set dataSource(value) { - this.ds = value; - this.isRecycleList = false; - if (this.hasAttribute('tree')) { - this.renderTreeTable(); - } else { - this.renderTable(); - } + // this.ds = value; + // this.isRecycleList = false; + // if (this.hasAttribute('tree')) { + // this.renderTreeTable(); + // } else { + // this.renderTable(); + // } + this.columnResizeEnable = false; + this.recycleDataSource = value; } get recycleDataSource() { @@ -351,7 +366,11 @@ export class LitTable extends HTMLElement { } if (this.hasAttribute('tree')) { this.value = value; - this.recycleDs = this.meauseTreeRowElement(value, RedrawTreeForm.Expand); + if (this.shadowRoot?.querySelector('.expand')) { + this.shadowRoot!.querySelector('.expand')!.querySelector('.top')!.name = 'up'; + this.shadowRoot!.querySelector('.expand')!.querySelector('.bottom')!.name = 'down'; + } + this.recycleDs = this.meauseTreeRowElement(value, RedrawTreeForm.Retract); } else { this.recycleDs = this.meauseAllRowHeight(value); } @@ -480,12 +499,15 @@ export class LitTable extends HTMLElement { injectColumns() { this.columns = this.st!.assignedElements(); + this.columns.forEach((column) => { + if (column.tagName === 'LIT-TABLE-COLUMN') { + this.gridTemplateColumns.push(column.getAttribute('width') || '1fr'); + } + }); } setStatus(list: any, status: boolean) { - if (!status) { - this.tableElement!.scrollTop = 0; - } + this.tableElement!.scrollTop = 0; for (let item of list) { item.status = status; if (item.children != undefined && item.children.length > 0) { @@ -555,8 +577,8 @@ export class LitTable extends HTMLElement { box.appendChild(checkbox); rowElement.appendChild(box); } - let area: Array = [], - gridTemplateColumns: Array = []; + let area: Array = []; + this.gridTemplateColumns = []; let resolvingArea = (columns: any, x: any, y: any) => { columns.forEach((a: any, i: any) => { if (!area[y]) area[y] = []; @@ -586,33 +608,36 @@ export class LitTable extends HTMLElement { x++; let h: any = document.createElement('div'); h.classList.add('td'); - if (a.hasAttribute('isExpand')) { + if ((this.hasAttribute('tree') && i > 1) || (!this.hasAttribute('tree') && i > 0)) { + let resizeDiv: HTMLDivElement = document.createElement('div'); + resizeDiv.classList.add('resize'); + h.appendChild(resizeDiv); + this.resizeEventHandler(rowElement, resizeDiv, i); + } + if (a.hasAttribute('retract')) { let expand = document.createElement('div'); expand.classList.add('expand'); expand.style.display = 'grid'; h.append(expand); - let bottom = document.createElement('lit-icon') as LitIcon; - bottom.classList.add('down'); - bottom.name = 'down'; - expand.append(bottom); let top = document.createElement('lit-icon') as LitIcon; top.classList.add('top'); top.name = 'up'; expand.append(top); - if (a.hasAttribute('retract')) { - top.name = 'down'; - bottom.name = 'up'; - } + let bottom = document.createElement('lit-icon') as LitIcon; + bottom.classList.add('bottom'); + bottom.name = 'down'; + expand.append(bottom); + expand.addEventListener('click', (e) => { - if (top.name !== 'up' && bottom.name !== 'down') { - top.name = 'up'; - bottom.name = 'down'; + if (top.name == 'up' && bottom.name == 'down') { + top.name = 'down'; + bottom.name = 'up'; // 一键展开 this.setStatus(this.value, true); this.recycleDs = this.meauseTreeRowElement(this.value, RedrawTreeForm.Expand); } else { - top.name = 'down'; - bottom.name = 'up'; + top.name = 'up'; + bottom.name = 'down'; // 一键收起 this.setStatus(this.value, false); this.recycleDs = this.meauseTreeRowElement(this.value, RedrawTreeForm.Retract); @@ -657,6 +682,9 @@ export class LitTable extends HTMLElement { h.appendChild(upSvg); h.appendChild(downSvg); h.onclick = () => { + if (this.isResize || this.resizeColumnIndex !== -1) { + return; + } this?.shadowRoot?.querySelectorAll('.td-order svg').forEach((it: any) => { it.setAttribute('fill', 'let(--dark-color1,#212121)'); it.sortType = 0; @@ -703,54 +731,17 @@ export class LitTable extends HTMLElement { }; } h.style.justifyContent = a.getAttribute('align'); - gridTemplateColumns.push(a.getAttribute('width') || '1fr'); + this.gridTemplateColumns.push(a.getAttribute('width') || '1fr'); h.style.gridArea = key; - // 根据进程、线程、状态、优先级展开 - if ( - a.title === 'State/Process/Thread' || - a.title === 'Process/Thread/State' || - a.title === 'Priority/State' - ) { - let labelArr = a.title.split('/'); - for (let i = 0; i < labelArr.length; i++) { - let titleLabel = document.createElement('label'); - titleLabel.style.cursor = 'pointer'; - i == 0 ? (titleLabel.textContent = labelArr[i]) : (titleLabel.textContent = '/' + labelArr[i]); - h.appendChild(titleLabel); - titleLabel.addEventListener('click', (e) => { - if ( - (titleLabel.textContent?.includes('State') && i === 0) || - (titleLabel.textContent?.includes('Process') && i === 0) || - (titleLabel.textContent?.includes('Priority') && i === 0) - ) { - this.setStatus(this.value, false); - this.recycleDs = this.meauseTreeRowElement(this.value, RedrawTreeForm.Retract); - } else if ( - (titleLabel.textContent?.includes('Process') && i === 1) || - (titleLabel.textContent?.includes('Thread') && i === 1) - ) { - for (let item of this.value) { - item.status = true; - if (item.children != undefined && item.children.length > 0) { - this.setStatus(item.children, false); - } - } - this.recycleDs = this.meauseTreeRowElement(this.value, RedrawTreeForm.Retract); - } else if ( - (titleLabel.textContent?.includes('Thread') && i === 2) || - (titleLabel.textContent?.includes('State') && i === 2) || - (titleLabel.textContent?.includes('State') && i === 1) - ) { - this.setStatus(this.value, true); - this.recycleDs = this.meauseTreeRowElement(this.value, RedrawTreeForm.Expand); - } - }); - } - } else { + + let labelArr = a.title.split('/'); + for (let i = 0; i < labelArr.length; i++) { let titleLabel = document.createElement('label'); - titleLabel.textContent = a.title; + titleLabel.style.cursor = 'pointer'; + i == 0 ? (titleLabel.textContent = labelArr[i]) : (titleLabel.textContent = '/' + labelArr[i]); h.appendChild(titleLabel); } + if (a.hasAttribute('fixed')) { this.fixed(h, a.getAttribute('fixed'), '#42b983'); } @@ -764,15 +755,14 @@ export class LitTable extends HTMLElement { if (!rows[i]) rows[i] = array[j - 1][i]; } }); - this.gridTemplateColumns = gridTemplateColumns.join(' '); if (this.selectable) { let s = area.map((a) => '"_checkbox_ ' + a.map((aa: any) => aa.t).join(' ') + '"').join(' '); - rowElement.style.gridTemplateColumns = '60px ' + gridTemplateColumns.join(' '); + rowElement.style.gridTemplateColumns = '60px ' + this.gridTemplateColumns.join(' '); rowElement.style.gridTemplateRows = `repeat(${area.length},1fr)`; rowElement.style.gridTemplateAreas = s; } else { let s = area.map((a) => '"' + a.map((aa: any) => aa.t).join(' ') + '"').join(' '); - rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); + rowElement.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); rowElement.style.gridTemplateRows = `repeat(${area.length},1fr)`; rowElement.style.gridTemplateAreas = s; } @@ -786,6 +776,80 @@ export class LitTable extends HTMLElement { this.tableElement!.addEventListener('mouseout', (ev) => this.mouseOut()); } + private isResize: boolean = false; + private resizeColumnIndex: number = -1; + private resizeDownX: number = 0; + private columnMinWidth: number = 50; + private beforeResizeWidth1: number = 0; + private beforeResizeWidth2: number = 0; + + resizeEventHandler(header: HTMLDivElement, element: HTMLDivElement, index: number){ + header.addEventListener('mousemove', (event) => { + if (!this.columnResizeEnable) return; + if (this.isResize) { + let width = event.clientX - this.resizeDownX; + header.style.cursor = 'col-resize'; + let preWidth = this.beforeResizeWidth1, nowWidth = this.beforeResizeWidth2; + if (width < 0) { + preWidth = Math.max(this.beforeResizeWidth1 + width, this.columnMinWidth); + nowWidth = (this.beforeResizeWidth1 - preWidth) + this.beforeResizeWidth2; + } + if (width > 0) { + nowWidth = Math.max(this.beforeResizeWidth2 - width, this.columnMinWidth); + preWidth = (this.beforeResizeWidth2 - nowWidth) + this.beforeResizeWidth1; + } + this.gridTemplateColumns[this.resizeColumnIndex - 1] = `${preWidth}px`; + this.gridTemplateColumns[this.resizeColumnIndex] = `${nowWidth}px`; + header.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); + this.shadowRoot!.querySelectorAll('.tr').forEach((tr) => { + if (this.hasAttribute('tree')) { + tr.style.gridTemplateColumns = this.gridTemplateColumns.slice(1).join(' '); + } else { + tr.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); + } + }); + event.preventDefault(); + event.stopPropagation(); + } else { + header.style.cursor = 'pointer'; + } + }); + header.addEventListener('mouseup', (event) => { + if (!this.columnResizeEnable) return; + this.isResize = false; + this.resizeDownX = 0; + header.style.cursor = 'pointer'; + setTimeout(() => { + this.resizeColumnIndex = -1; + }, 100); + event.stopPropagation(); + event.preventDefault(); + }); + header.addEventListener('mouseleave', (event) => { + if (!this.columnResizeEnable) return; + event.stopPropagation(); + event.preventDefault(); + this.isResize = false; + this.resizeDownX = 0; + this.resizeColumnIndex = -1; + header.style.cursor = 'pointer'; + }); + element.addEventListener('mousedown', (event)=> { + if (!this.columnResizeEnable) return; + this.isResize = true; + this.resizeColumnIndex = index; + this.resizeDownX = event.clientX; + let pre = (header.childNodes.item(this.resizeColumnIndex - 1) as HTMLDivElement); + let now = (header.childNodes.item(this.resizeColumnIndex) as HTMLDivElement); + this.beforeResizeWidth1 = pre.clientWidth; + this.beforeResizeWidth2 = now.clientWidth; + event.stopPropagation(); + }); + element.addEventListener('click',(event) => { + event.stopPropagation(); + }); + } + // Is called when the custom element is removed from the document DOM. disconnectedCallback() {} @@ -806,257 +870,6 @@ export class LitTable extends HTMLElement { } } - renderTable() { - if (!this.columns) return; - if (!this.ds) return; // If no data source is set, it is returned directly - this.normalDs = []; - this.tbodyElement!.innerHTML = ''; // Clear the table contents - this.ds.forEach((rowData: any) => { - let tblRowElement = document.createElement('div'); - tblRowElement.classList.add('tr'); - // @ts-ignore - tblRowElement.data = rowData; - let gridTemplateColumns: Array = []; - // If the table is configured with selectable (select row mode) add a checkbox at the head of the line alone - if (this.selectable) { - let tblBox = document.createElement('div'); - tblBox.style.display = 'flex'; - tblBox.style.justifyContent = 'center'; - tblBox.style.alignItems = 'center'; - tblBox.classList.add('td'); - let checkbox = document.createElement('lit-checkbox'); - checkbox.classList.add('row-checkbox'); - checkbox.onchange = (e: any) => { - // Checkbox checking affects whether the div corresponding to the row has a checked attribute for marking - if (e.detail.checked) { - tblRowElement.setAttribute('checked', ''); - } else { - tblRowElement.removeAttribute('checked'); - } - }; - this.getWheelStatus(tblBox); - tblBox.appendChild(checkbox); - tblRowElement.appendChild(tblBox); - } - this.tableColumns!.forEach((tblColumn) => { - let dataIndex = tblColumn.getAttribute('data-index') || '1'; - gridTemplateColumns.push(tblColumn.getAttribute('width') || '1fr'); - if (tblColumn.template) { - // If you customize the rendering, you get the nodes from the template - // @ts-ignore - let cloneNode = tblColumn.template.render(rowData).content.cloneNode(true); - let tblCustomDiv = document.createElement('div'); - tblCustomDiv.classList.add('td'); - tblCustomDiv.style.wordBreak = 'break-all'; - tblCustomDiv.style.whiteSpace = 'pre-wrap'; - tblCustomDiv.style.justifyContent = tblColumn.getAttribute('align') || ''; - if (tblColumn.hasAttribute('fixed')) { - this.fixed(tblCustomDiv, tblColumn.getAttribute('fixed') || '', '#ffffff'); - } - this.getWheelStatus(tblCustomDiv); - tblCustomDiv.append(cloneNode); - tblRowElement.append(tblCustomDiv); - } else { - let tblDiv = document.createElement('div'); - tblDiv.classList.add('td'); - tblDiv.style.wordBreak = 'break-all'; - tblDiv.style.whiteSpace = 'pre-wrap'; - tblDiv.title = rowData[dataIndex]; - tblDiv.style.justifyContent = tblColumn.getAttribute('align') || ''; - if (tblColumn.hasAttribute('fixed')) { - this.fixed(tblDiv, tblColumn.getAttribute('fixed') || '', '#ffffff'); - } - this.getWheelStatus(tblDiv); - tblDiv.innerHTML = this.formatName(dataIndex, rowData[dataIndex]); - tblRowElement.append(tblDiv); - } - }); - if (this.selectable) { - // If the table with selection is preceded by a 60px column - tblRowElement.style.gridTemplateColumns = '60px ' + gridTemplateColumns.join(' '); - } else { - tblRowElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); - } - tblRowElement.onclick = (e) => { - this.dispatchEvent( - new CustomEvent('row-click', { - detail: { - rowData, - data: rowData, - callBack: (isSelected: boolean) => { - //是否爲单选 - if (isSelected) { - this.clearAllSelection(rowData); - } - this.setSelectedRow(rowData.isSelected, [tblRowElement]); - }, - }, - composed: true, - }) - ); - }; - this.normalDs.push(tblRowElement); - this.tbodyElement!.append(tblRowElement); - }); - } - - renderTreeTable() { - if (!this.columns) return; - if (!this.ds) return; - this.tbodyElement!.innerHTML = ''; - this.treeElement!.innerHTML = ''; - let ids = JSON.parse(this.getAttribute('tree') || `["id","pid"]`); - let toTreeData = (data: any, id: any, pid: any) => { - let cloneData = JSON.parse(JSON.stringify(data)); - return cloneData.filter((father: any) => { - let branchArr = cloneData.filter((child: any) => father[id] == child[pid]); - branchArr.length > 0 ? (father['children'] = branchArr) : ''; - return !father[pid]; - }); - }; - let treeData = toTreeData(this.ds, ids[0], ids[1]); - let offset = 30; - let offsetVal = offset; - const drawRow = (arr: any, parentNode: any) => { - arr.forEach((rowData: any) => { - let treeTblRowElement = document.createElement('div'); - treeTblRowElement.classList.add('tr'); - // @ts-ignore - treeTblRowElement.data = rowData; - let gridTemplateColumns: Array = []; - if (this.selectable) { - let treeTblDiv = document.createElement('div'); - treeTblDiv.style.display = 'flex'; - treeTblDiv.style.justifyContent = 'center'; - treeTblDiv.style.alignItems = 'center'; - treeTblDiv.classList.add('td'); - let checkbox = document.createElement('lit-checkbox'); - checkbox.classList.add('row-checkbox'); - checkbox.onchange = (e: any) => { - if (e.detail.checked) { - treeTblRowElement.setAttribute('checked', ''); - } else { - treeTblRowElement.removeAttribute('checked'); - } - const changeChildNode = (rowElement: any, checked: any) => { - let id = rowElement.getAttribute('id'); - let pid = rowElement.getAttribute('pid'); - this.shadowRoot!.querySelectorAll(`div[pid=${id}]`).forEach((element) => { - // @ts-ignore - element.querySelector('.row-checkbox')!.checked = checked; - if (checked) { - element.setAttribute('checked', ''); - } else { - element.removeAttribute('checked'); - } - changeChildNode(element, checked); - }); - }; - changeChildNode(treeTblRowElement, e.detail.checked); - }; - this.getWheelStatus(treeTblDiv); - treeTblDiv.appendChild(checkbox); - treeTblRowElement.appendChild(treeTblDiv); - } - this.tableColumns!.forEach((treeTblColumn, index) => { - let dataIndex = treeTblColumn.getAttribute('data-index'); - let treeTblEl; - if (index !== 0) { - gridTemplateColumns.push(treeTblColumn.getAttribute('width') || '1fr'); - if (treeTblColumn.template) { - // @ts-ignore - let cloneNode = treeTblColumn.template.render(rowData).content.cloneNode(true); - treeTblEl = document.createElement('div'); - treeTblEl.classList.add('td'); - treeTblEl.style.wordBreak = 'break-all'; - treeTblEl.style.justifyContent = treeTblColumn.getAttribute('align') || ''; - if (treeTblColumn.hasAttribute('fixed')) { - this.fixed(treeTblEl, treeTblColumn.getAttribute('fixed') || '', '#ffffff'); - } - this.getWheelStatus(treeTblEl); - treeTblEl.append(cloneNode); - } else { - treeTblEl = document.createElement('div'); - treeTblEl.style.justifyContent = treeTblColumn.getAttribute('align') || ''; - treeTblEl.style.wordBreak = 'break-all'; - treeTblEl.classList.add('td'); - if (treeTblColumn.hasAttribute('fixed')) { - this.fixed(treeTblEl, treeTblColumn.getAttribute('fixed') || '', '#ffffff'); - } - // @ts-ignore - treeTblEl.innerHTML = this.formatName(dataIndex, rowData[dataIndex]); - } - this.getWheelStatus(treeTblEl); - treeTblRowElement.append(treeTblEl); - } else { - this.treeElement!.style.width = treeTblColumn.getAttribute('width') || '260px'; - let treeElement = document.createElement('div'); - treeElement.classList.add('tree-first-body'); - if (treeTblColumn.template) { - // @ts-ignore - let firstCloneNode = treeTblColumn.template.render(rowData).content.cloneNode(true); - treeTblEl = document.createElement('div'); - treeTblEl.classList.add('td'); - treeTblEl.style.justifyContent = treeTblColumn.getAttribute('align') || ''; - if (treeTblColumn.hasAttribute('fixed')) { - this.fixed(treeTblEl, treeTblColumn.getAttribute('fixed') || '', '#ffffff'); - } - this.getWheelStatus(treeTblEl); - treeTblEl.append(firstCloneNode); - } else { - treeTblEl = document.createElement('div'); - treeTblEl.style.justifyContent = treeTblColumn.getAttribute('align') || ''; - treeTblEl.classList.add('td'); - if (treeTblColumn.hasAttribute('fixed')) { - this.fixed(treeTblEl, treeTblColumn.getAttribute('fixed') || '', '#ffffff'); - } - this.getWheelStatus(treeTblEl); - // @ts-ignore - treeTblEl.innerHTML = this.formatName(dataIndex, rowData[dataIndex]); - } - if (rowData.children && rowData.children.length > 0) { - let treeTblIcon = document.createElement('lit-icon'); - treeTblIcon.classList.add('tree-icon'); - // @ts-ignore - treeTblIcon.name = 'minus-square'; - treeElement.append(treeTblIcon); - treeElement.append(treeTblEl); - treeElement.style.paddingLeft = offsetVal - 30 + 'px'; - } else { - treeElement.append(treeTblEl); - treeElement.style.paddingLeft = offsetVal + 'px'; - } - this.treeElement!.append(treeElement); - } - }); - if (this.selectable) { - treeTblRowElement.style.gridTemplateColumns = '60px ' + gridTemplateColumns.join(' '); - } else { - treeTblRowElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); - } - treeTblRowElement.onclick = (e) => { - this.dispatchEvent( - new CustomEvent('row-click', { - detail: rowData, - composed: true, - }) - ); - }; - treeTblRowElement.style.cursor = 'pointer'; - parentNode.append(treeTblRowElement); - treeTblRowElement.setAttribute('id', rowData[ids[0]]); - treeTblRowElement.setAttribute('pid', rowData[ids[1]]); - treeTblRowElement.setAttribute('expend', ''); - if (rowData.children && rowData.children.length > 0) { - offsetVal = offsetVal + offset; - drawRow(rowData.children, parentNode); - offsetVal = offsetVal - offset; - } - }); - }; - drawRow(treeData, this.tbodyElement); - } - getCheckRows() { // @ts-ignore return [...this.shadowRoot!.querySelectorAll('div[class=tr][checked]')] @@ -1299,7 +1112,6 @@ export class LitTable extends HTMLElement { createNewTreeTableElement(rowData: TableRowObject): any { let newTableElement = document.createElement('div'); newTableElement.classList.add('tr'); - let gridTemplateColumns: Array = []; let treeTop = 0; if (this.treeElement!.children?.length > 0) { let transX = Number((this.treeElement?.lastChild as HTMLElement).style.transform.replace(/[^0-9]/gi, '')); @@ -1309,15 +1121,16 @@ export class LitTable extends HTMLElement { let dataIndex = column.getAttribute('data-index') || '1'; let td: any; if (index === 0) { + let text = this.formatName(dataIndex, rowData.data[dataIndex]); if (column.template) { td = column.template.render(rowData.data).content.cloneNode(true); td.template = column.template; td.title = rowData.data[dataIndex]; } else { td = document.createElement('div'); - td.innerHTML = this.formatName(dataIndex, rowData.data[dataIndex]); + td.innerHTML = text; td.dataIndex = dataIndex; - td.title = rowData.data[dataIndex]; + td.title = text; } if (rowData.data.children && rowData.data.children.length > 0 && !rowData.data.hasNext) { let btn = this.createExpandBtn(rowData); @@ -1403,22 +1216,21 @@ export class LitTable extends HTMLElement { this.treeElement?.append(td); this.currentTreeDivList.push(td); } else { - gridTemplateColumns.push(column.getAttribute('width') || '1fr'); td = document.createElement('div'); td.classList.add('td'); td.style.overflow = 'hidden'; td.style.textOverflow = 'ellipsis'; td.style.whiteSpace = 'nowrap'; - td.title = rowData.data[dataIndex]; + let text = this.formatName(dataIndex, rowData.data[dataIndex]); + td.title = text; td.dataIndex = dataIndex; td.style.justifyContent = column.getAttribute('align') || 'flex-start'; if (column.template) { td.appendChild(column.template.render(rowData.data).content.cloneNode(true)); td.template = column.template; } else { - td.innerHTML = this.formatName(dataIndex, rowData.data[dataIndex]); + td.innerHTML = text; } - this.getWheelStatus(td); newTableElement.append(td); } }); @@ -1427,7 +1239,7 @@ export class LitTable extends HTMLElement { lastChild.style.transform = `translateY(${treeTop}px)`; } (newTableElement as any).data = rowData.data; - newTableElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); + newTableElement.style.gridTemplateColumns = this.gridTemplateColumns.slice(1).join(' '); newTableElement.style.position = 'absolute'; newTableElement.style.top = '0px'; newTableElement.style.left = '0px'; @@ -1628,10 +1440,8 @@ export class LitTable extends HTMLElement { createNewTableElement(rowData: any): any { let newTableElement = document.createElement('div'); newTableElement.classList.add('tr'); - let gridTemplateColumns: Array = []; this?.columns?.forEach((column: any) => { let dataIndex = column.getAttribute('data-index') || '1'; - gridTemplateColumns.push(column.getAttribute('width') || '1fr'); let td: any; td = document.createElement('div'); td.classList.add('td'); @@ -1640,14 +1450,14 @@ export class LitTable extends HTMLElement { td.style.whiteSpace = 'nowrap'; td.dataIndex = dataIndex; td.style.justifyContent = column.getAttribute('align') || 'flex-start'; - td.title = rowData.data[dataIndex]; + let text = this.formatName(dataIndex, rowData.data[dataIndex]); + td.title = text; if (column.template) { td.appendChild(column.template.render(rowData.data).content.cloneNode(true)); td.template = column.template; } else { - td.innerHTML = this.formatName(dataIndex, rowData.data[dataIndex]); + td.innerHTML = text; } - this.getWheelStatus(td); newTableElement.append(td); }); newTableElement.onclick = () => { @@ -1661,7 +1471,7 @@ export class LitTable extends HTMLElement { } (newTableElement as any).data = rowData.data; newTableElement.style.cursor = 'pointer'; - newTableElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); + newTableElement.style.gridTemplateColumns = this.gridTemplateColumns.join(' '); newTableElement.style.position = 'absolute'; newTableElement.style.top = '0px'; newTableElement.style.left = '0px'; @@ -1694,8 +1504,9 @@ export class LitTable extends HTMLElement { .content.cloneNode(true).innerHTML; } else { let dataIndex = this.columns![0].getAttribute('data-index') || '1'; - firstElement.innerHTML = this.formatName(dataIndex, rowObject.data[dataIndex]); - firstElement.title = rowObject.data[dataIndex]; + let text = this.formatName(dataIndex, rowObject.data[dataIndex]); + firstElement.innerHTML = text; + firstElement.title = text; } if (rowObject.children && rowObject.children.length > 0 && !rowObject.data.hasNext) { let btn = this.createExpandBtn(rowObject); @@ -1764,15 +1575,16 @@ export class LitTable extends HTMLElement { } } let dataIndex = this.columns![idx].getAttribute('data-index') || '1'; + let text = this.formatName(dataIndex, rowObject.data[dataIndex]); if ((this.columns![idx] as any).template) { (child as HTMLElement).innerHTML = ''; (child as HTMLElement).appendChild( (this.columns![idx] as any).template.render(rowObject.data).content.cloneNode(true) ); - (child as HTMLElement).title = rowObject.data[dataIndex]; + (child as HTMLElement).title = text; } else { - (child as HTMLElement).innerHTML = this.formatName(dataIndex, rowObject.data[dataIndex]); - (child as HTMLElement).title = rowObject.data[dataIndex]; + (child as HTMLElement).innerHTML = text; + (child as HTMLElement).title = text; } }); if (element.style.display == 'none') { @@ -2065,15 +1877,6 @@ export class LitTable extends HTMLElement { } divElement.title = rowData.data.symbolName; } - - getWheelStatus(element: any) { - element.addEventListener('wheel', (event: WheelEvent) => { - if (element.scrollWidth !== element.offsetWidth) { - event.preventDefault(); - } - element.scrollLeft += event.deltaY; - }); - } } // 表格默认是展开还是收起的 diff --git a/ide/src/trace/SpApplication.ts b/ide/src/trace/SpApplication.ts index 185e98f6c8609172a4923ff15917086567d25c87..07a2b61d578cdf1e89894ef0f5c39187d26907e0 100644 --- a/ide/src/trace/SpApplication.ts +++ b/ide/src/trace/SpApplication.ts @@ -51,6 +51,8 @@ import { ColorUtils } from './component/trace/base/ColorUtils.js'; import { SpStatisticsHttpUtil } from '../statistics/util/SpStatisticsHttpUtil.js'; import { FlagsConfig, SpFlags } from './component/SpFlags.js'; import './component/SpFlags.js'; +import './component/trace/base/CustomThemeColor.js'; +import { CustomThemeColor, Theme } from './component/trace/base/CustomThemeColor.js'; @element('sp-application') export class SpApplication extends BaseElement { @@ -238,7 +240,6 @@ export class SpApplication extends BaseElement { :host(:not([search])) .search-container { display: none; } - :host(:not([search])) .search-container .search { background-color: var(--dark-background5,#F6F6F6); } @@ -330,11 +331,10 @@ export class SpApplication extends BaseElement { font-size: 20px; color: var(--dark-color1,#47A7E0); } - .chart-filter { + .chart-filter .custom-color { visibility: hidden; z-index: -1; } - :host([chart_filter]) .chart-filter { display: grid; grid-template-rows: min-content min-content min-content max-content auto; @@ -347,6 +347,18 @@ export class SpApplication extends BaseElement { z-index: 1001; top: 0; } + :host([custom-color]) .custom-color { + display: grid; + grid-template-rows: min-content min-content min-content max-content auto; + overflow-y: auto; + height: 100%; + visibility: visible; + position: absolute; + width: 50%; + right: 0; + z-index: 1002; + top: 0; + } .filter-config { opacity: 1; visibility: hidden; @@ -391,6 +403,7 @@ export class SpApplication extends BaseElement { +
`; @@ -423,7 +436,10 @@ export class SpApplication extends BaseElement { let search = this.shadowRoot?.querySelector('.search-container') as HTMLElement; let sidebarButton: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('.sidebar-button'); let chartFilter = this.shadowRoot?.querySelector('.chart-filter') as TraceRowConfig; + let customColor = this.shadowRoot?.querySelector('.custom-color') as CustomThemeColor; + mainMenu!.setAttribute('main_menu', '1'); chartFilter!.setAttribute('mode', ''); + customColor!.setAttribute('mode', ''); let childNodes = [ spSystemTrace, spRecordTrace, @@ -436,51 +452,6 @@ export class SpApplication extends BaseElement { spRecordTemplate, spFlags, ]; - let sideColor = mainMenu.shadowRoot?.querySelector('.color') as HTMLDivElement; - //修改侧边导航栏配色 - sideColor!.onclick = (e) => { - let backgroundColor = sessionStorage.getItem('backgroundColor'); - let menu: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#main-menu'); - let menuGroup = mainMenu.shadowRoot?.querySelectorAll('lit-main-menu-group'); - let menuItem = menu!.shadowRoot?.querySelectorAll('lit-main-menu-item'); - if (backgroundColor == 'white' || !backgroundColor) { - menu!.style.backgroundColor = '#262f3c'; - menu!.style.transition = '1s'; - menuGroup!.forEach((item) => { - let groupName = item!.shadowRoot!.querySelector('.group-name') as LitMainMenuGroup; - let groupDescribe = item!.shadowRoot!.querySelector('.group-describe') as LitMainMenuGroup; - groupName.style.color = 'white'; - groupDescribe.style.color = 'white'; - }); - menuItem!.forEach((item) => { - item.style.color = 'white'; - }); - ColorUtils.MD_PALETTE = ColorUtils.FUNC_COLOR_A; - ColorUtils.FUNC_COLOR = ColorUtils.FUNC_COLOR_A; - } else { - menu!.style.backgroundColor = 'white'; - menu!.style.transition = '1s'; - menuGroup!.forEach((item) => { - let groupName = item!.shadowRoot!.querySelector('.group-name') as LitMainMenuGroup; - let groupDescribe = item!.shadowRoot!.querySelector('.group-describe') as LitMainMenuGroup; - groupName.style.color = 'black'; - groupDescribe.style.color = '#92959b'; - }); - menuItem!.forEach((item) => { - item.style.color = 'var(--dark-color,rgba(0,0,0,0.6))'; - }); - ColorUtils.MD_PALETTE = ColorUtils.FUNC_COLOR_B; - ColorUtils.FUNC_COLOR = ColorUtils.FUNC_COLOR_B; - } - - sessionStorage.setItem('backgroundColor', menu!.style.backgroundColor); - if (this.colorTransiton) { - clearTimeout(this.colorTransiton); - } - this.colorTransiton = setTimeout(() => { - menu!.style.transition = '0s'; - }, 1000); - }; window.subscribe(window.SmartEvent.UI.MenuTrace, () => showContent(spSystemTrace!)); window.subscribe(window.SmartEvent.UI.Error, (err) => { @@ -556,6 +527,18 @@ export class SpApplication extends BaseElement { } }); + let customColorShow = this.shadowRoot + ?.querySelector('lit-main-menu')! + .shadowRoot!.querySelector('.customColor') as HTMLDivElement; + customColorShow.addEventListener('click', (ev) => { + if (this!.hasAttribute('custom-color')) { + this!.removeAttribute('custom-color'); + customColor.cancelOperate(); + } else { + this!.setAttribute('custom-color', ''); + } + }); + //打开侧边栏 sidebarButton!.onclick = (e) => { let menu: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#main-menu'); @@ -600,6 +583,8 @@ export class SpApplication extends BaseElement { }); filterConfig.style.visibility = 'visible'; } else { + that.removeAttribute('custom-color'); + customColor.cancelOperate(); menu!.style.pointerEvents = 'none'; sidebarButton!.style.pointerEvents = 'none'; that.search = litSearch.isLoading; @@ -948,6 +933,12 @@ export class SpApplication extends BaseElement { }; function openTraceFile(ev: any, isClickHandle?: boolean) { + that.removeAttribute('custom-color'); + if (window.localStorage.getItem('Theme') == 'dark') { + that.changeTheme(Theme.DARK); + } else { + that.changeTheme(Theme.LIGHT); + } openFileInit(); if (that.vs && isClickHandle) { Cmd.openFileDialog().then((res: string) => { @@ -1249,6 +1240,82 @@ export class SpApplication extends BaseElement { } } + /** + * 修改颜色或者主题,重新绘制侧边栏和泳道图 + * @param theme 当前主题(深色和浅色) + * @param colorsArray 预览的情况下传入 + */ + changeTheme(theme: Theme, colorsArray?: Array) { + let systemTrace = this.shadowRoot!.querySelector('#sp-system-trace'); + let menu: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#main-menu'); + let menuGroup = menu!.shadowRoot?.querySelectorAll('lit-main-menu-group'); + let menuItem = menu!.shadowRoot?.querySelectorAll('lit-main-menu-item'); + let customColor = this.shadowRoot?.querySelector('.custom-color') as CustomThemeColor; + if (!colorsArray) { + customColor.setRadioChecked(theme); + } + if (theme === Theme.DARK) { + menu!.style.backgroundColor = '#262f3c'; + menu!.style.transition = '1s'; + menuGroup!.forEach((item) => { + let groupName = item!.shadowRoot!.querySelector('.group-name') as LitMainMenuGroup; + let groupDescribe = item!.shadowRoot!.querySelector('.group-describe') as LitMainMenuGroup; + groupName.style.color = 'white'; + groupDescribe.style.color = 'white'; + }); + menuItem!.forEach((item) => { + item.style.color = 'white'; + }); + if ( + !colorsArray && + window.localStorage.getItem('DarkThemeColors') && + ColorUtils.FUNC_COLOR_B !== JSON.parse(window.localStorage.getItem('DarkThemeColors')!) + ) { + ColorUtils.MD_PALETTE = JSON.parse(window.localStorage.getItem('DarkThemeColors')!); + ColorUtils.FUNC_COLOR = JSON.parse(window.localStorage.getItem('DarkThemeColors')!); + } else if (colorsArray) { + ColorUtils.MD_PALETTE = colorsArray; + ColorUtils.FUNC_COLOR = colorsArray; + } else { + ColorUtils.MD_PALETTE = ColorUtils.FUNC_COLOR_B; + ColorUtils.FUNC_COLOR = ColorUtils.FUNC_COLOR_B; + } + } else { + menu!.style.backgroundColor = 'white'; + menu!.style.transition = '1s'; + menuGroup!.forEach((item) => { + let groupName = item!.shadowRoot!.querySelector('.group-name') as LitMainMenuGroup; + let groupDescribe = item!.shadowRoot!.querySelector('.group-describe') as LitMainMenuGroup; + groupName.style.color = 'black'; + groupDescribe.style.color = '#92959b'; + }); + menuItem!.forEach((item) => { + item.style.color = 'black'; + }); + if ( + !colorsArray && + window.localStorage.getItem('LightThemeColors') && + ColorUtils.FUNC_COLOR_A !== JSON.parse(window.localStorage.getItem('LightThemeColors')!) + ) { + ColorUtils.MD_PALETTE = JSON.parse(window.localStorage.getItem('LightThemeColors')!); + ColorUtils.FUNC_COLOR = JSON.parse(window.localStorage.getItem('LightThemeColors')!); + } else if (colorsArray) { + ColorUtils.MD_PALETTE = colorsArray; + ColorUtils.FUNC_COLOR = colorsArray; + } else { + ColorUtils.MD_PALETTE = ColorUtils.FUNC_COLOR_A; + ColorUtils.FUNC_COLOR = ColorUtils.FUNC_COLOR_A; + } + } + systemTrace!.timerShaftEL!.rangeRuler!.draw(); + if (this.colorTransiton) { + clearTimeout(this.colorTransiton); + } + this.colorTransiton = setTimeout(() => { + menu!.style.transition = '0s'; + }, 1000); + } + private downloadOnLineFile(url: string, download: boolean, openFileHandler: (path: string) => void) { if (download) { let api = `${window.location.origin}/download-file`; @@ -1278,7 +1345,8 @@ export class SpApplication extends BaseElement { private getUrlParams(url: string) { const _url = url || window.location.href; const _urlParams = _url.match(/([?&])(.+?=[^&]+)/gim); - return _urlParams ? _urlParams.reduce((a: any, b) => { + return _urlParams + ? _urlParams.reduce((a: any, b) => { const value = b.slice(1).split('='); a[`${value[0]}`] = decodeURIComponent(value[1]); return a; diff --git a/ide/src/trace/bean/FrameChartStruct.ts b/ide/src/trace/bean/FrameChartStruct.ts index 8fb13425e5be540b2e04fbc208d8a9c4151914ce..cfaff1d2c15f01ae5cf7a4f1d0870f18dff21400 100644 --- a/ide/src/trace/bean/FrameChartStruct.ts +++ b/ide/src/trace/bean/FrameChartStruct.ts @@ -56,6 +56,8 @@ export class ChartStruct extends BaseStruct { isChartSelect: boolean = false; // 是否为点选的调用链 isChartSelectParent: boolean = false; // 用来显示灰色 tsArray: Array = []; + countArray: Array = []; + durArray: Array = []; } export enum ChartMode { @@ -166,4 +168,4 @@ function getHeatColor(widthPercentage: number): string { function isHover(data: ChartStruct): boolean { return ChartStruct.hoverFuncStruct === data; -} +} \ No newline at end of file diff --git a/ide/src/trace/bean/NativeHook.ts b/ide/src/trace/bean/NativeHook.ts index f868568d1aeac940704b6efa025d505f2fde2378..34ae8c57de478093a0efadf59881667d04b80a64 100644 --- a/ide/src/trace/bean/NativeHook.ts +++ b/ide/src/trace/bean/NativeHook.ts @@ -160,3 +160,8 @@ export class NativeEvent { heapSize: number = 0; eventType: string = ''; } + +export class NativeMemoryExpression { + includeLib: Map = new Map(); + abandonLib: Map = new Map(); +} diff --git a/ide/src/trace/bean/StateProcessThread.ts b/ide/src/trace/bean/StateProcessThread.ts index 29a8f5330c91bdb3e130dd68a05b920ef662f926..03f4efa68e59cc18184847db9477f08d67a8f313 100644 --- a/ide/src/trace/bean/StateProcessThread.ts +++ b/ide/src/trace/bean/StateProcessThread.ts @@ -19,11 +19,12 @@ export class SliceGroup { state?: string; tid?: number; pid?: number; + status: boolean = false; minDuration: number = 0; maxDuration: number = 0; wallDuration: number = 0; avgDuration: string = ''; - children?: Array + children?: Array; } export class SPTChild { @@ -51,4 +52,5 @@ export class Priority extends SliceGroup { endState: string = ''; dur: number = 0; priority: number = 0; + status: boolean = false; } diff --git a/ide/src/trace/component/SpHelp.ts b/ide/src/trace/component/SpHelp.ts index cad0b6445149a22c37500ed2d74532abec23fff1..9de6f77f6b5bce6136d79c61c88674623c5855b6 100644 --- a/ide/src/trace/component/SpHelp.ts +++ b/ide/src/trace/component/SpHelp.ts @@ -29,15 +29,13 @@ export class SpHelp extends BaseElement { set dark(dark: boolean) { if (dark) { - this.setAttribute('dark', `${ dark}`); + this.setAttribute('dark', `${dark}`); } else { this.removeAttribute('dark'); } this.appContent!.innerHTML = '`; + `/application/doc/quickstart_device_record.html?${that.dark} width="100%" height="100%">`; }, }, { @@ -83,9 +79,7 @@ export class SpHelp extends BaseElement { }); that.appContent!.innerHTML = ' { if (result) { HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_VERSION, false).then((version) => { - let deviceVersionItem = SpRecordTrace.supportVersions.filter((item) => version.indexOf(item) != -1); - if (deviceVersionItem.length > 0) { - SpRecordTrace.selectVersion = deviceVersionItem[0]; - this.setDeviceVersionSelect(SpRecordTrace.selectVersion); - } else { - SpRecordTrace.selectVersion = SpRecordTrace.supportVersions[0]; - this.setDeviceVersionSelect(SpRecordTrace.selectVersion); - } + SpRecordTrace.selectVersion = this.getDeviceVersion(version); + this.setDeviceVersionSelect(SpRecordTrace.selectVersion); this.nativeMemoryHideBySelectVersion(); this.traceCommand!.hdcCommon = PluginConvertUtils.createHdcCmd( PluginConvertUtils.BeanToCmdTxt(this.makeRequest(), false), @@ -509,6 +503,14 @@ export class SpRecordTrace extends BaseElement { } } + getDeviceVersion(version: string): string { + if (version.indexOf('3.2') != -1) { + return '3.2'; + } else if (version.indexOf('4.') != -1) { + return '4.0+'; + } + return '3.2'; + } freshMenuDisable(disable: boolean): void { let mainMenu = this.sp!.shadowRoot?.querySelector('#main-menu') as LitMainMenu; mainMenu.menus?.forEach((men) => { @@ -773,7 +775,7 @@ export class SpRecordTrace extends BaseElement { private nativeMemoryHideBySelectVersion() { let divConfigs = this.spAllocations?.shadowRoot?.querySelectorAll('.version-controller'); if (divConfigs) { - if (Number(SpRecordTrace.selectVersion) >= 4.0) { + if (SpRecordTrace.selectVersion != '3.2') { for (let divConfig of divConfigs) { divConfig!.style.zIndex = '1'; } @@ -786,12 +788,7 @@ export class SpRecordTrace extends BaseElement { } private selectedDevice(deviceVersion: string): void { - let deviceVersionItem = SpRecordTrace.supportVersions.filter((item) => deviceVersion.indexOf(item) != -1); - if (deviceVersionItem.length > 0) { - SpRecordTrace.selectVersion = deviceVersionItem[0]; - } else { - SpRecordTrace.selectVersion = SpRecordTrace.supportVersions[0]; - } + SpRecordTrace.selectVersion = this.getDeviceVersion(deviceVersion); this.setDeviceVersionSelect(SpRecordTrace.selectVersion); } @@ -983,7 +980,7 @@ export class SpRecordTrace extends BaseElement { fileChoose: false, clickHandler: function (ev: InputEvent): void { let divConfigs = that.spAllocations?.shadowRoot?.querySelectorAll('.version-controller'); - if ((!SpRecordTrace.selectVersion || Number(SpRecordTrace.selectVersion) < 4.0) && divConfigs) { + if ((!SpRecordTrace.selectVersion || SpRecordTrace.selectVersion === '3.2') && divConfigs) { for (let divConfig of divConfigs) { divConfig!.style.zIndex = '-1'; } @@ -1404,7 +1401,7 @@ export class SpRecordTrace extends BaseElement { ); } - if (this.spAllocations!.appProcess != '') { + if (this.spAllocations!.appProcess !== '' && this.spAllocations!.startSamp) { request.pluginConfigs.push(this.createNativePluginConfig(reportingFrequency)); } if (this.spRecordPerf!.startSamp) { @@ -1859,7 +1856,7 @@ export class SpRecordTrace extends BaseElement { let pid = 0; let processName = ''; let processId = ''; - if (this.spAllocations!.startup_mode && Number(SpRecordTrace.selectVersion) >= 4.0) { + if (this.spAllocations!.startup_mode && SpRecordTrace.selectVersion !== '3.2') { processName = appProcess; } else { if (appProcess.indexOf('(') != -1) { @@ -1885,7 +1882,7 @@ export class SpRecordTrace extends BaseElement { fpUnwind: this.spAllocations!.fp_unwind, blocked: true, }; - if (Number(SpRecordTrace.selectVersion) >= 4.0) { + if (SpRecordTrace.selectVersion !== '3.2') { nativeConfig.callframeCompress = true; nativeConfig.recordAccurately = this.spAllocations!.record_accurately; nativeConfig.offlineSymbolization = this.spAllocations!.offline_symbolization; diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts index 665a0b272013300af42761ba82cb300523e8aa0e..db441304dc71fdc39e62db752c7f06304fbb81e5 100644 --- a/ide/src/trace/component/SpSystemTrace.ts +++ b/ide/src/trace/component/SpSystemTrace.ts @@ -127,9 +127,9 @@ export class CurrentSlicesTime { @element('sp-system-trace') export class SpSystemTrace extends BaseElement { - static mouseCurrentPosition = 0; - static offsetMouse = 0; - static moveable = true; + mouseCurrentPosition = 0; + offsetMouse = 0; + isMouseLeftDown = false; static scrollViewWidth = 0; static isCanvasOffScreen = true; static DATA_DICT: Map = new Map(); @@ -235,10 +235,6 @@ export class SpSystemTrace extends BaseElement { } initElements(): void { - let sideColor = - document!.querySelector('body > sp-application')?.shadowRoot?.querySelector!( - '#main-menu' - )?.shadowRoot?.querySelector('div.bottom > div.color'); this.traceSheetEL = this.shadowRoot?.querySelector('.trace-sheet'); let rightButton: HTMLElement | null | undefined = this.traceSheetEL?.shadowRoot ?.querySelector('#current-selection > tabpane-current-selection') @@ -337,32 +333,18 @@ export class SpSystemTrace extends BaseElement { this.refreshFavoriteCanvas(); this.refreshCanvas(true); }); - sideColor?.addEventListener('click', (event: any) => { - requestAnimationFrame(() => this.refreshCanvas(true)); - }); document?.addEventListener('triangle-flag', (event: any) => { - const time = event.detail.time; - const type = event.detail.type; - if (time.length > 1) { - return; - } - if (time === '' && type === 'square') { - let temporaryTime = this.timerShaftEL?.drawTriangle(time, type); - if (event.detail.timeCallback && temporaryTime) event.detail.timeCallback(temporaryTime); - } - this.clearTriangle(this.timerShaftEL!.sportRuler!.flagList); - // 框选的宽度 - let rangeSelectWidth = TraceRow.rangeSelectObject!.endX! - TraceRow.rangeSelectObject!.startX!; - // 平均一个旗子占的宽度,一个三角旗子大概18px,部分重合也可以看清,所以只要大于15暂时就画旗子 - if (rangeSelectWidth / time.length > 15) { - for (const item of time) { - this.timerShaftEL?.drawTriangle(item, type); - } - } else { - this.timerShaftEL!.sportRuler!.time = time; - this.timerShaftEL!.sportRuler?.draw(); - } + let temporaryTime = this.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type); + if (event.detail.timeCallback && temporaryTime) event.detail.timeCallback(temporaryTime); + }); + + document?.addEventListener('number_calibration', (event: any) => { + this.timerShaftEL!.sportRuler!.times = event.detail.time; + this.timerShaftEL!.sportRuler!.counts = event.detail.counts; + this.timerShaftEL!.sportRuler!.durations = event.detail.durations; + this.timerShaftEL!.sportRuler?.draw(); }); + document?.addEventListener('flag-change', (event: any) => { this.timerShaftEL?.modifyFlagList(event.detail); if (event.detail.hidden) { @@ -1303,7 +1285,7 @@ export class SpSystemTrace extends BaseElement { } // 清除上一次点击调用栈产生的三角旗子 private clearTriangle(flagList: Array) { - this.timerShaftEL!.sportRuler!.time = []; + this.timerShaftEL!.sportRuler!.times = []; for (var i = 0; i < flagList.length; i++) { if (flagList[i].type === 'triangle') { flagList.splice(i, 1); @@ -1693,6 +1675,13 @@ export class SpSystemTrace extends BaseElement { ev.stopPropagation(); return; } + if (ev.ctrlKey) { + ev.preventDefault(); + this.style.cursor = 'move'; + this.isMouseLeftDown = true; + this.mouseCurrentPosition = ev.clientX; + return; + } TraceRow.isUserInteraction = true; if (this.isMouseInSheet(ev)) return; this.observerScrollHeightEnable = false; @@ -1741,6 +1730,14 @@ export class SpSystemTrace extends BaseElement { ev.stopPropagation(); return; } + if (ev.ctrlKey) { + ev.preventDefault(); + this.offsetMouse = 0; + this.mouseCurrentPosition = 0; + this.isMouseLeftDown = false; + this.style.cursor = 'default'; + return; + } TraceRow.isUserInteraction = false; this.rangeSelect.isMouseDown = false; if ((window as any).isSheetMove) return; @@ -2033,6 +2030,9 @@ export class SpSystemTrace extends BaseElement { ev.preventDefault(); return; } + if (ev.ctrlKey && ev.button == 0 && this.isMouseLeftDown) { + this.translateByMouseMove(ev); + } this.inFavoriteArea = this.favoriteRowsEL?.containPoint(ev); if ((window as any).isSheetMove) return; if (this.isMouseInSheet(ev)) { @@ -2449,6 +2449,18 @@ export class SpSystemTrace extends BaseElement { let task = () => { if (threadRow) { let findEntry = threadRow!.dataList!.find((dat) => dat.startTime === d.startTime && dat.dur! > 0); + if (!findEntry) { + findEntry = { + processName: d.processName, + threadName: d.name, + startTime: d.startTime, + state: 'Running', + dur: 0, + pid: d.processId, + tid: d.tid, + cpu: d.cpu, + } as ThreadStruct; + } if ( findEntry!.startTime! + findEntry!.dur! < TraceRow.range!.startNS || findEntry!.startTime! > TraceRow.range!.endNS @@ -3276,39 +3288,20 @@ export class SpSystemTrace extends BaseElement { } } - myMouseMove = (ev: MouseEvent) => { - if (ev.ctrlKey) { - ev.preventDefault(); - SpSystemTrace.offsetMouse = ev.clientX - SpSystemTrace.mouseCurrentPosition; - let eventA = new KeyboardEvent('keypress', { - key: 'a', - code: '65', - keyCode: 65, - }); - let eventD = new KeyboardEvent('keypress', { - key: 'd', - code: '68', - keyCode: 68, - }); - if (ev.button == 0) { - if (SpSystemTrace.offsetMouse < 0 && SpSystemTrace.moveable) { - // 向右拖动,则泳道图右移 - this.timerShaftEL!.documentOnKeyPress(eventD); - setTimeout(() => { - this.timerShaftEL!.documentOnKeyUp(eventD); - }, 350); - } - if (SpSystemTrace.offsetMouse > 0 && SpSystemTrace.moveable) { - // 向左拖动,则泳道图左移 - this.timerShaftEL!.documentOnKeyPress(eventA); - setTimeout(() => { - this.timerShaftEL!.documentOnKeyUp(eventA); - }, 350); - } - } - SpSystemTrace.moveable = false; + translateByMouseMove(ev: MouseEvent): void { + ev.preventDefault(); + let offset = 0; + if (this.offsetMouse === 0) { + this.offsetMouse = ev.clientX; + offset = ev.clientX - this.mouseCurrentPosition; + } else { + offset = ev.clientX - this.offsetMouse; } - }; + this.offsetMouse = ev.clientX; + const rangeRuler = this.timerShaftEL?.getRangeRuler()!; + + rangeRuler.translate(offset); + } connectedCallback() { this.initPointToEvent(); @@ -3339,40 +3332,6 @@ export class SpSystemTrace extends BaseElement { document.addEventListener('keyup', this.documentOnKeyUp); document.addEventListener('contextmenu', this.onContextMenuHandler); - /** - * 获取并保存鼠标当前的x轴坐标位置,配合ctrl+鼠标左键拖动完成泳道图的左移或右移 - */ - this.addEventListener( - 'mousedown', - (e) => { - if (e.ctrlKey) { - e.preventDefault(); - this.style.cursor = 'move'; - SpSystemTrace.moveable = true; - SpSystemTrace.mouseCurrentPosition = e.clientX; - } - }, - { passive: false } - ); - /** - * ctrl+鼠标移动,实现泳道图左移或者右移。 - */ - this.addEventListener('mousemove', (ev) => throttle(this.myMouseMove, 350, ev)(), { passive: false }); - - this.addEventListener( - 'mouseup', - (e) => { - if (e.ctrlKey) { - e.preventDefault(); - SpSystemTrace.offsetMouse = 0; - SpSystemTrace.mouseCurrentPosition = 0; - SpSystemTrace.moveable = false; - this.style.cursor = 'default'; - } - }, - { passive: false } - ); - /** * 泳道图中添加ctrl+鼠标滚轮事件,对泳道图进行放大缩小。 * 鼠标滚轮事件转化为键盘事件,keyPress和keyUp两个事件需要配合使用, diff --git a/ide/src/trace/component/chart/FrameChart.ts b/ide/src/trace/component/chart/FrameChart.ts index 051830b7cdf82e25336039a85e53b839662df8c8..69cae06ff70f5787f11851050294a01805e3be1a 100644 --- a/ide/src/trace/component/chart/FrameChart.ts +++ b/ide/src/trace/component/chart/FrameChart.ts @@ -588,30 +588,6 @@ export class FrameChart extends BaseElement { } } - /** - * 判断当前node的整条调用栈都与之前点击node的相同 - * 则认为是上次选择的node - * @param data 每一个函数node - * @returns 是否为点选的那个node - */ - private isSelectedNode(data: ChartStruct): boolean { - let select = ChartStruct.selectFuncStruct; - while (data?.parent && select?.parent) { - if ( - select?.depth === data.depth && - select.symbol === data.symbol && - select.lib === data.lib && - select.addr === data.addr - ) { - data = data.parent; - select = select.parent; - } else { - return false; - } - } - return !data.parent && !select?.parent; - } - /** * 点选后重绘火焰图 */ @@ -749,8 +725,12 @@ export class FrameChart extends BaseElement { // 重新绘图 this.clickRedraw(); document.dispatchEvent( - new CustomEvent('triangle-flag', { - detail: { time: ChartStruct.selectFuncStruct.tsArray, type: 'triangle' }, + new CustomEvent('number_calibration', { + detail: { + time: ChartStruct.selectFuncStruct.tsArray, + counts: ChartStruct.selectFuncStruct.countArray, + durations: ChartStruct.selectFuncStruct.durArray, + }, }) ); } diff --git a/ide/src/trace/component/chart/SpFileSystemChart.ts b/ide/src/trace/component/chart/SpFileSystemChart.ts index 4c1e248c9032fb2fda432df981b912c6baf6f188..a000cd371780dc12a766c1b1f1523772fa2d7c45 100644 --- a/ide/src/trace/component/chart/SpFileSystemChart.ts +++ b/ide/src/trace/component/chart/SpFileSystemChart.ts @@ -77,6 +77,7 @@ export class SpFileSystemChart { fsFolder.style.height = '40px'; fsFolder.folder = true; fsFolder.name = `EBPF`; /* & I/O Latency */ + fsFolder.addTemplateTypes('HiEBpf'); fsFolder.favoriteChangeHandler = this.trace.favoriteChangeHandler; fsFolder.selectChangeHandler = this.trace.selectChangeHandler; fsFolder.supplier = () => new Promise>((resolve) => resolve([])); diff --git a/ide/src/trace/component/chart/SpFrameTimeChart.ts b/ide/src/trace/component/chart/SpFrameTimeChart.ts index bd00198c171550e5348541d87bda2aba7121b85a..797f374a3411bef12f487a1701d2a3fb9b24062a 100644 --- a/ide/src/trace/component/chart/SpFrameTimeChart.ts +++ b/ide/src/trace/component/chart/SpFrameTimeChart.ts @@ -25,7 +25,7 @@ import { queryFrameDynamicData, queryFrameSpacing, queryFrameTimeData, - queryPhysicalData + queryPhysicalData, queryTraceType } from '../../database/SqlLite.js'; import { JanksStruct } from '../../bean/JanksStruct.js'; import { ns2xByTimeShaft, PairPoint } from '../../database/ui-worker/ProcedureWorkerCommon.js'; @@ -50,6 +50,7 @@ import { EmptyRender } from '../../database/ui-worker/ProcedureWorkerCPU.js'; export class SpFrameTimeChart { private trace: SpSystemTrace; private flagConfig: Params | undefined; + private isTxtTraceType: boolean = false; constructor(trace: SpSystemTrace) { this.trace = trace; @@ -59,7 +60,13 @@ export class SpFrameTimeChart { let frameTimeData = await queryFrameTimeData(); if (frameTimeData.length > 0) { let frameTimeLineRow: TraceRow = await this.initFrameTimeLine(); - await this.initExpectedChart(frameTimeLineRow); + let traceType = await queryTraceType(); + if (traceType.length > 0 && traceType[0].value.startsWith('txt')) { + this.isTxtTraceType = true; + } + if (!this.isTxtTraceType) { + await this.initExpectedChart(frameTimeLineRow); + } await this.initActualChart(frameTimeLineRow); } } @@ -634,6 +641,9 @@ export class SpFrameTimeChart { let depthArray = []; for (let index: number = 0; index < frameActualData.length; index++) { let it = frameActualData[index]; + if (this.isTxtTraceType) { + it.jank_tag = 0; + } if (!it.dur || it.dur < 0) { continue; } diff --git a/ide/src/trace/component/chart/SpHiPerf.ts b/ide/src/trace/component/chart/SpHiPerf.ts index 03b6e5f6647c9130b91dd2c2efd1341a5a5e47b3..b600b27b0618881b20fb3d7616d82e62d5accbc8 100644 --- a/ide/src/trace/component/chart/SpHiPerf.ts +++ b/ide/src/trace/component/chart/SpHiPerf.ts @@ -114,6 +114,10 @@ export class SpHiPerf { row.rowParentId = ''; row.folder = true; row.style.height = '40px'; + if (SpChartManager.APP_STARTUP_PID_ARR.find(pid => pid === process.pid) !== undefined) { + row.addTemplateTypes('AppStartup'); + } + row.addTemplateTypes('HiPerf'); if (SpHiPerf.stringResult?.existA === true) { row.name = `HiPerf (All)`; } else { @@ -232,9 +236,7 @@ export class SpHiPerf { row.rowParentId = 'HiPerf'; row.rowHidden = !this.rowFolder.expansion; row.folder = true; - if (SpChartManager.APP_STARTUP_PID_ARR.find(pid => pid === process.pid) !== undefined) { - row.addTemplateTypes('AppStartup'); - } + row.name = `${process.processName || 'Process'} [${process.pid}]`; row.folderPaddingLeft = 6; row.style.height = '40px'; diff --git a/ide/src/trace/component/chart/SpHiSysEventChart.ts b/ide/src/trace/component/chart/SpHiSysEventChart.ts index 70e6a43f48ea67d9e9f6fd68fec1635f8700307b..7d55b8b2f7f62c1ee7bbace49e80b1102f06e061 100644 --- a/ide/src/trace/component/chart/SpHiSysEventChart.ts +++ b/ide/src/trace/component/chart/SpHiSysEventChart.ts @@ -129,6 +129,7 @@ export class SpHiSysEventChart { this.energyTraceRow.rowType = TraceRow.ROW_TYPE_ENERGY; this.energyTraceRow.rowParentId = ''; this.energyTraceRow.folder = true; + this.energyTraceRow.addTemplateTypes('HiSysEvent'); this.energyTraceRow.name = 'Energy'; this.energyTraceRow.style.height = '40px'; this.energyTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; diff --git a/ide/src/trace/component/chart/SpLogChart.ts b/ide/src/trace/component/chart/SpLogChart.ts index 89a94f4a8c7513aee9148e5fdfa66ae3d4f9ca65..b18565ef291d8bea3ddcc59d44064f74e572be87 100644 --- a/ide/src/trace/component/chart/SpLogChart.ts +++ b/ide/src/trace/component/chart/SpLogChart.ts @@ -19,6 +19,8 @@ import { queryLogData } from '../../database/SqlLite.js'; import { renders } from '../../database/ui-worker/ProcedureWorker.js'; import { LogRender, LogStruct } from '../../database/ui-worker/ProcedureWorkerLog.js'; +const ONE_DAY_NS = 86400000000000; + export class SpLogChart { private trace: SpSystemTrace; @@ -27,7 +29,8 @@ export class SpLogChart { } async init() { - let dataArray = await queryLogData(); + let oneDayTime = (window as any).recordEndNS - ONE_DAY_NS; + let dataArray = await queryLogData(oneDayTime); if (dataArray.length === 0) { return; } diff --git a/ide/src/trace/component/chart/SpNativeMemoryChart.ts b/ide/src/trace/component/chart/SpNativeMemoryChart.ts index e7f01d08d25ddd6f42cd7821004705520b1b1f55..bd34a8efa6524d5ee11bcbf51a1d6ff2257dad3e 100644 --- a/ide/src/trace/component/chart/SpNativeMemoryChart.ts +++ b/ide/src/trace/component/chart/SpNativeMemoryChart.ts @@ -65,6 +65,7 @@ export class SpNativeMemoryChart { nativeRow.style.height = '40px'; nativeRow.rowParentId = ''; nativeRow.folder = true; + nativeRow.addTemplateTypes('NativeMemory'); nativeRow.name = `Native Memory` + process; nativeRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; nativeRow.selectChangeHandler = this.trace.selectChangeHandler; diff --git a/ide/src/trace/component/chart/SpProcessChart.ts b/ide/src/trace/component/chart/SpProcessChart.ts index a212e22cef397a5600e0da348c90ac09b9c9a64e..0bff720447a74f712b5b408cd7c43174f528db05 100644 --- a/ide/src/trace/component/chart/SpProcessChart.ts +++ b/ide/src/trace/component/chart/SpProcessChart.ts @@ -34,7 +34,7 @@ import { queryProcessThreads, queryProcessThreadsByTable, queryStartupPidArray, - queryThreadData, + queryThreadData, queryTraceType, } from '../../database/SqlLite.js'; import { Utils } from '../trace/base/Utils.js'; import { info } from '../../../log/Log.js'; @@ -50,6 +50,7 @@ import { ns2xByTimeShaft } from '../../database/ui-worker/ProcedureWorkerCommon. import { AppStartupRender, AppStartupStruct } from '../../database/ui-worker/ProcedureWorkerAppStartup.js'; import { SoRender, SoStruct } from '../../database/ui-worker/ProcedureWorkerSoInit.js'; import { FlagsConfig } from '../SpFlags.js'; +import { JanksStruct } from '../../bean/JanksStruct.js'; export class SpProcessChart { private readonly trace: SpSystemTrace; @@ -200,11 +201,18 @@ export class SpProcessChart { let allJankProcess: Array = []; let allExpectedProcess: Array = []; let allActualProcess: Array = []; + let isTxtTraceType: boolean = false; if (allJankProcessData.length > 0) { allJankProcessData.forEach((name, index) => { allJankProcess.push(name.pid!); }); - allExpectedProcess = await queryAllExpectedData(); + let traceType = await queryTraceType(); + if (traceType.length > 0 && traceType[0].value.startsWith('txt')) { + isTxtTraceType = true; + } + if (!isTxtTraceType) { + allExpectedProcess = await queryAllExpectedData(); + } allActualProcess = await queryAllActualData(); } let allTaskPoolPid = await queryAllTaskPoolPid(); @@ -276,142 +284,144 @@ export class SpProcessChart { */ let actualRow: TraceRow | null = null; let expectedRow: TraceRow | null = null; - if (allJankProcess.indexOf(it.pid) > -1 && allExpectedProcess.length > 0) { - let expectedData = allExpectedProcess.filter((ite) => ite.pid == it.pid); - if (expectedData.length > 0) { - // @ts-ignore - let isIntersect = (a: JanksStruct, b: JanksStruct): boolean => - Math.max(a.ts + a.dur, b.ts + b.dur) - Math.min(a.ts, b.ts) < a.dur + b.dur; - let depthArray: any = []; - for (let j = 0 ; j < expectedData.length ; j++) { - let expectedItem = expectedData[j]; - if (expectedItem.cmdline != 'render_service') { - expectedItem.frame_type = 'app'; - } else { - expectedItem.frame_type = expectedItem.cmdline; - } - if (!expectedItem.dur || expectedItem.dur < 0) { - continue; - } - if (depthArray.length === 0) { - expectedItem.depth = 0; - depthArray.push(expectedItem); - } else { - if (isIntersect(depthArray[0], expectedItem)) { - if (isIntersect(depthArray[depthArray.length - 1], expectedItem)) { - expectedItem.depth = depthArray.length; - depthArray.push(expectedItem); - } - } else { - expectedItem.depth = 0; - depthArray = [expectedItem]; - } - } - } - let max = Math.max(...expectedData.map((it) => it.depth || 0)) + 1; - let maxHeight = max * 20; - expectedRow = TraceRow.skeleton(); - let timeLineType = expectedData[0].type; - expectedRow.rowId = `${ timeLineType }-${ it.pid }`; - expectedRow.asyncFuncName = it.processName; - expectedRow.asyncFuncNamePID = it.pid; - expectedRow.rowType = TraceRow.ROW_TYPE_JANK; - expectedRow.rowParentId = `${ it.pid }`; - expectedRow.rowHidden = !processRow.expansion; - expectedRow.style.width = '100%'; - expectedRow.style.height = `${ maxHeight }px`; - expectedRow.setAttribute('height', `${ maxHeight }`); - expectedRow.setAttribute('frame_type', expectedData[0].frame_type); - expectedRow.name = 'Expected Timeline'; - expectedRow.addTemplateTypes('FrameTimeline'); - expectedRow.setAttribute('children', ''); - expectedRow.supplier = (): Promise => - new Promise((resolve) => { - resolve(expectedData); - }); - expectedRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - expectedRow.selectChangeHandler = this.trace.selectChangeHandler; - expectedRow.onThreadHandler = (useCache): void => { - let context = expectedRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - expectedRow!.canvasSave(context); - (renders['jank'] as JankRender).renderMainThread( - { - context: context, - useCache: useCache, - type: 'expected_frame_timeline_slice', - }, - expectedRow! - ); - expectedRow!.canvasRestore(context); - }; - processRow.addChildTraceRow(expectedRow); - let actualData = allActualProcess.filter((ite) => ite.pid == it.pid); - if (actualData.length > 0) { - let isIntersect = (a: any, b: any): boolean => - Math.max(a.ts + a.dur, b.ts + b.dur) - Math.min(a.ts, b.ts) < a.dur + b.dur; + if (allJankProcess.indexOf(it.pid) > -1) { + let isIntersect = (a: JanksStruct, b: JanksStruct): boolean => + Math.max(a.ts! + a.dur!, b.ts! + b.dur!) - Math.min(a.ts!, b.ts!) < a.dur! + b.dur!; + if (!isTxtTraceType) { + let expectedData = allExpectedProcess.filter((ite) => ite.pid == it.pid); + if (expectedData.length > 0) { let depthArray: any = []; - for (let j = 0 ; j < actualData.length ; j++) { - let actualItem = actualData[j]; - if (actualItem.cmdline != 'render_service') { - actualItem.frame_type = 'app'; + for (let j = 0 ; j < expectedData.length ; j++) { + let expectedItem = expectedData[j]; + if (expectedItem.cmdline != 'render_service') { + expectedItem.frame_type = 'app'; } else { - actualItem.frame_type = actualItem.cmdline; + expectedItem.frame_type = expectedItem.cmdline; } - if (!actualItem.dur || actualItem.dur < 0) { + if (!expectedItem.dur || expectedItem.dur < 0) { continue; } if (depthArray.length === 0) { - actualItem.depth = 0; - depthArray.push(actualItem); + expectedItem.depth = 0; + depthArray.push(expectedItem); } else { - if (isIntersect(depthArray[0], actualItem)) { - if (isIntersect(depthArray[depthArray.length - 1], actualItem)) { - actualItem.depth = depthArray.length; - depthArray.push(actualItem); - } else { - actualItem.depth = depthArray.length - 1; - depthArray[length - 1] = actualItem; + if (isIntersect(depthArray[0], expectedItem)) { + if (isIntersect(depthArray[depthArray.length - 1], expectedItem)) { + expectedItem.depth = depthArray.length; + depthArray.push(expectedItem); } } else { - actualItem.depth = 0; - depthArray = [actualItem]; + expectedItem.depth = 0; + depthArray = [expectedItem]; } } } - let max = Math.max(...actualData.map((it) => it.depth || 0)) + 1; + let max = Math.max(...expectedData.map((it) => it.depth || 0)) + 1; let maxHeight = max * 20; - actualRow = TraceRow.skeleton(); - let timeLineType = actualData[0].type; - actualRow.rowId = `${ timeLineType }-${ it.pid }`; - actualRow.rowType = TraceRow.ROW_TYPE_JANK; - actualRow.rowParentId = `${ it.pid }`; - actualRow.rowHidden = !processRow.expansion; - actualRow.style.width = '100%'; - actualRow.style.height = `${ maxHeight }px`; - actualRow.setAttribute('height', `${ maxHeight }`); - actualRow.name = 'Actual Timeline'; - actualRow.addTemplateTypes('FrameTimeline'); - actualRow.setAttribute('frame_type', actualData[0].frame_type); - actualRow.setAttribute('children', ''); - actualRow.dataList = actualData; - actualRow.supplier = (): Promise => new Promise((resolve) => resolve(actualData)); - actualRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - actualRow.selectChangeHandler = this.trace.selectChangeHandler; - actualRow.onThreadHandler = (useCache): void => { - let context = actualRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - actualRow!.canvasSave(context); + expectedRow = TraceRow.skeleton(); + let timeLineType = expectedData[0].type; + expectedRow.rowId = `${ timeLineType }-${ it.pid }`; + expectedRow.asyncFuncName = it.processName; + expectedRow.asyncFuncNamePID = it.pid; + expectedRow.rowType = TraceRow.ROW_TYPE_JANK; + expectedRow.rowParentId = `${ it.pid }`; + expectedRow.rowHidden = !processRow.expansion; + expectedRow.style.width = '100%'; + expectedRow.style.height = `${ maxHeight }px`; + expectedRow.setAttribute('height', `${ maxHeight }`); + expectedRow.setAttribute('frame_type', expectedData[0].frame_type); + expectedRow.name = 'Expected Timeline'; + expectedRow.addTemplateTypes('FrameTimeline'); + expectedRow.setAttribute('children', ''); + expectedRow.supplier = (): Promise => + new Promise((resolve) => { + resolve(expectedData); + }); + expectedRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + expectedRow.selectChangeHandler = this.trace.selectChangeHandler; + expectedRow.onThreadHandler = (useCache): void => { + let context = expectedRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + expectedRow!.canvasSave(context); (renders['jank'] as JankRender).renderMainThread( { context: context, useCache: useCache, - type: 'actual_frame_timeline_slice', + type: 'expected_frame_timeline_slice', }, - actualRow! + expectedRow! ); - actualRow!.canvasRestore(context); + expectedRow!.canvasRestore(context); }; - processRow.addChildTraceRow(actualRow); + processRow.addChildTraceRow(expectedRow); + } + } + let actualData = allActualProcess.filter((ite) => ite.pid == it.pid); + if (actualData.length > 0) { + let depthArray: any = []; + for (let j = 0 ; j < actualData.length ; j++) { + let actualItem = actualData[j]; + if (isTxtTraceType) { + actualItem.jank_tag = 0; + } + if (actualItem.cmdline != 'render_service') { + actualItem.frame_type = 'app'; + } else { + actualItem.frame_type = actualItem.cmdline; + } + if (!actualItem.dur || actualItem.dur < 0) { + continue; + } + if (depthArray.length === 0) { + actualItem.depth = 0; + depthArray.push(actualItem); + } else { + if (isIntersect(depthArray[0], actualItem)) { + if (isIntersect(depthArray[depthArray.length - 1], actualItem)) { + actualItem.depth = depthArray.length; + depthArray.push(actualItem); + } else { + actualItem.depth = depthArray.length - 1; + depthArray[length - 1] = actualItem; + } + } else { + actualItem.depth = 0; + depthArray = [actualItem]; + } + } } + let max = Math.max(...actualData.map((it) => it.depth || 0)) + 1; + let maxHeight = max * 20; + actualRow = TraceRow.skeleton(); + let timeLineType = actualData[0].type; + actualRow.rowId = `${ timeLineType }-${ it.pid }`; + actualRow.rowType = TraceRow.ROW_TYPE_JANK; + actualRow.rowParentId = `${ it.pid }`; + actualRow.rowHidden = !processRow.expansion; + actualRow.style.width = '100%'; + actualRow.style.height = `${ maxHeight }px`; + actualRow.setAttribute('height', `${ maxHeight }`); + actualRow.name = 'Actual Timeline'; + actualRow.addTemplateTypes('FrameTimeline'); + actualRow.setAttribute('frame_type', actualData[0].frame_type); + actualRow.setAttribute('children', ''); + actualRow.dataList = actualData; + actualRow.supplier = (): Promise => new Promise((resolve) => resolve(actualData)); + actualRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + actualRow.selectChangeHandler = this.trace.selectChangeHandler; + actualRow.onThreadHandler = (useCache): void => { + let context = actualRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + actualRow!.canvasSave(context); + (renders['jank'] as JankRender).renderMainThread( + { + context: context, + useCache: useCache, + type: 'actual_frame_timeline_slice', + }, + actualRow! + ); + actualRow!.canvasRestore(context); + }; + processRow.addChildTraceRow(actualRow); } } let offsetYTimeOut: any = undefined; diff --git a/ide/src/trace/component/chart/SpVmTrackerChart.ts b/ide/src/trace/component/chart/SpVmTrackerChart.ts index f90a57f28fec6d9abe0cb6db5060ac2598a162d9..0d24074ade516593cd920337372d87204ee0d9be 100644 --- a/ide/src/trace/component/chart/SpVmTrackerChart.ts +++ b/ide/src/trace/component/chart/SpVmTrackerChart.ts @@ -88,6 +88,7 @@ export class VmTrackerChart { let VmTrackerRow = TraceRow.skeleton(); VmTrackerRow.rowId = 'VmTrackerRow'; VmTrackerRow.rowType = TraceRow.ROW_TYPE_VM_TRACKER; + VmTrackerRow.addTemplateTypes('ProcessMemory'); VmTrackerRow.rowParentId = ''; VmTrackerRow.style.height = '40px'; VmTrackerRow.index = 0; diff --git a/ide/src/trace/component/setting/SpAllocations.ts b/ide/src/trace/component/setting/SpAllocations.ts index 59bd8f79f2765704b9df7c6b785ff35f2fc993ea..417fb833db24d8079c114468b6193f2686db6cb3 100644 --- a/ide/src/trace/component/setting/SpAllocations.ts +++ b/ide/src/trace/component/setting/SpAllocations.ts @@ -33,14 +33,28 @@ export class SpAllocations extends BaseElement { private shareMemory: HTMLInputElement | null | undefined; private shareMemoryUnit: HTMLSelectElement | null | undefined; private filterMemory: HTMLInputElement | null | undefined; + private intervalResultInput: HTMLInputElement | null | undefined; private filterMemoryUnit: HTMLSelectElement | null | undefined; private fpUnWind: LitSwitch | null | undefined; + private statisticsSlider: LitSlider | null | undefined; private recordAccurately: LitSwitch | null | undefined; private offlineSymbol: LitSwitch | null | undefined; private startupMode: LitSwitch | null | undefined; private recordStatisticsResult: HTMLDivElement | null | undefined; + set startSamp(allocationStart: boolean) { + if (allocationStart) { + this.setAttribute('startSamp', ''); + } else { + this.removeAttribute('startSamp'); + } + } + + get startSamp(): boolean { + return this.hasAttribute('startSamp'); + } + get appProcess(): string { return this.processId!.value || ''; } @@ -118,19 +132,19 @@ export class SpAllocations extends BaseElement { initElements(): void { this.processId = this.shadowRoot?.getElementById('pid') as LitAllocationSelect; - let input = this.processId.shadowRoot?.querySelector('.multipleSelect') as HTMLDivElement; + let process = this.processId.shadowRoot?.querySelector('.multipleSelect') as HTMLDivElement; let sp = document.querySelector('sp-application') as SpApplication; let litSearch = sp?.shadowRoot?.querySelector('#lit-record-search') as LitSearch; let allocationProcessData: Array = []; - input.addEventListener('mousedown', (ev) => { - if (SpRecordTrace.serialNumber == '') { + process.addEventListener('mousedown', (ev) => { + if (SpRecordTrace.serialNumber === '') { this.processId!.processData = []; } }); - input.addEventListener('valuable', (ev) => { + process.addEventListener('valuable', (ev) => { this.dispatchEvent(new CustomEvent('addProbe', {})); }); - input.addEventListener('inputClick', () => { + process.addEventListener('inputClick', () => { allocationProcessData = []; if (this.startup_mode) { this.processId!.processData = []; @@ -153,12 +167,12 @@ export class SpAllocations extends BaseElement { this.offlineSymbol = this.shadowRoot?.getElementById('use_offline_symbolization') as LitSwitch; this.startupMode = this.shadowRoot?.getElementById('use_startup_mode') as LitSwitch; let stepValue = [0, 1, 10, 30, 60, 300, 600, 1800, 3600]; - let statisticsSlider = this.shadowRoot?.querySelector('#interval-slider') as LitSlider; + this.statisticsSlider = this.shadowRoot?.querySelector('#interval-slider') as LitSlider; this.recordStatisticsResult = this.shadowRoot?.querySelector( '.record-statistics-result' ) as HTMLDivElement; - statisticsSlider.sliderStyle = { + this.statisticsSlider.sliderStyle = { minRange: 0, maxRange: 3600, defaultValue: '3600', @@ -167,11 +181,11 @@ export class SpAllocations extends BaseElement { lineColor: 'var(--dark-color3,#46B1E3)', buttonColor: '#999999', }; - let parentElement = statisticsSlider!.parentNode as Element; - let intervalResultInput = this.shadowRoot?.querySelector('.interval-result') as HTMLInputElement; - intervalResultInput.value = statisticsSlider.sliderStyle.defaultValue; - statisticsSlider.addEventListener('input', (evt) => { - statisticsSlider!.sliderStyle = { + let parentElement = this.statisticsSlider!.parentNode as Element; + this.intervalResultInput = this.shadowRoot?.querySelector('.interval-result') as HTMLInputElement; + this.intervalResultInput.value = this.statisticsSlider.sliderStyle.defaultValue; + this.statisticsSlider.addEventListener('input', (evt) => { + this.statisticsSlider!.sliderStyle = { minRange: 0, maxRange: 3600, defaultValue: this.recordStatisticsResult!.getAttribute('percent') + '', @@ -180,67 +194,70 @@ export class SpAllocations extends BaseElement { lineColor: 'var(--dark-color3,#46B1E3)', buttonColor: '#999999', }; - intervalResultInput.style.color = 'var(--dark-color1,#000000)'; + this.intervalResultInput!.style.color = 'var(--dark-color1,#000000)'; if (this.recordStatisticsResult!.hasAttribute('percent')) { let step = Number(this.recordStatisticsResult!.getAttribute('percent')) / 450; this.recordStatisticsResult!.setAttribute('percentValue', stepValue[step] + ''); - intervalResultInput.value = stepValue[step] + ''; + this.intervalResultInput!.value = stepValue[step] + ''; } }); parentElement.setAttribute('percent', '3600'); - intervalResultInput.style.color = 'var(--dark-color1,#000000)'; - intervalResultInput.addEventListener('input', (ev) => { + this.intervalResultInput.style.color = 'var(--dark-color1,#000000)'; + this.intervalResultInput.addEventListener('input', (ev) => { if (this.recordStatisticsResult!.hasAttribute('percent')) { this.recordStatisticsResult!.removeAttribute('percent'); } - intervalResultInput.style.color = 'var(--dark-color1,#000000)'; - intervalResultInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; - intervalResultInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; - if (intervalResultInput.value.trim() == '') { - intervalResultInput.style.color = 'red'; + this.intervalResultInput!.style.color = 'var(--dark-color1,#000000)'; + this.intervalResultInput!.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; + this.intervalResultInput!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; + if (this.intervalResultInput!.value.trim() === '') { + this.intervalResultInput!.style.color = 'red'; parentElement.setAttribute('percent', '3600'); return; } - let memorySize = Number(intervalResultInput.value); - if (memorySize < statisticsSlider!.sliderStyle.minRange || memorySize > statisticsSlider!.sliderStyle.maxRange) { - intervalResultInput.style.color = 'red'; + let memorySize = Number(this.intervalResultInput!.value); + if ( + memorySize < this.statisticsSlider!.sliderStyle.minRange || + memorySize > this.statisticsSlider!.sliderStyle.maxRange + ) { + this.intervalResultInput!.style.color = 'red'; parentElement.setAttribute('percent', '3600'); } else { - statisticsSlider!.percent = intervalResultInput.value; - let htmlInputElement = statisticsSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; - htmlInputElement.value = intervalResultInput.value; - statisticsSlider!.sliderStyle = { + this.statisticsSlider!.percent = this.intervalResultInput!.value; + let htmlInputElement = this.statisticsSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; + htmlInputElement.value = this.intervalResultInput!.value; + this.statisticsSlider!.sliderStyle = { minRange: 0, maxRange: 3600, - defaultValue: intervalResultInput.value, + defaultValue: this.intervalResultInput!.value, resultUnit: 'S', stepSize: 1, lineColor: 'var(--dark-color3,#46B1E3)', buttonColor: '#999999', }; - parentElement.setAttribute('percent', intervalResultInput.value); - parentElement.setAttribute('percentValue', intervalResultInput.value); + parentElement.setAttribute('percent', this.intervalResultInput!.value); + parentElement.setAttribute('percentValue', this.intervalResultInput!.value); } }); - intervalResultInput.addEventListener('focusout', (ev) => { - if (intervalResultInput.value.trim() == '') { + this.intervalResultInput.addEventListener('focusout', (ev) => { + if (this.intervalResultInput!.value.trim() === '') { parentElement.setAttribute('percent', '3600'); - intervalResultInput.value = '3600'; - intervalResultInput.style.color = 'var(--dark-color,#6a6f77)'; - parentElement.setAttribute('percent', intervalResultInput.value); - parentElement.setAttribute('percentValue', intervalResultInput.value); - statisticsSlider!.percent = intervalResultInput.value; - let htmlInputElement = statisticsSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; - htmlInputElement.value = intervalResultInput.value; + this.intervalResultInput!.value = '3600'; + this.intervalResultInput!.style.color = 'var(--dark-color,#6a6f77)'; + parentElement.setAttribute('percent', this.intervalResultInput!.value); + parentElement.setAttribute('percentValue', this.intervalResultInput!.value); + this.statisticsSlider!.percent = this.intervalResultInput!.value; + let htmlInputElement = this.statisticsSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; + htmlInputElement.value = this.intervalResultInput!.value; } }); - statisticsSlider.shadowRoot?.querySelector('#slider')!.addEventListener('mouseup', (ev) => { + this.statisticsSlider.shadowRoot?.querySelector('#slider')!.addEventListener('mouseup', (ev) => { setTimeout(() => { let percentValue = this.recordStatisticsResult!.getAttribute('percent'); let index = Number(percentValue) / 450; index = index < 1 ? 0 : index; - intervalResultInput.value = stepValue[index] + ''; + this.intervalResultInput!.value = stepValue[index] + ''; this.recordStatisticsResult!.setAttribute('percentValue', stepValue[index] + ''); }); }); @@ -253,6 +270,61 @@ export class SpAllocations extends BaseElement { this.processId!.placeholder = 'please select process'; } }); + + let litSwitch = this.shadowRoot?.querySelector('lit-switch') as LitSwitch; + litSwitch.addEventListener('change', (event: any) => { + let detail = event.detail; + if (detail.checked) { + this.unDisable(); + } else { + this.disable(); + } + }); + this.disable(); + } + + private unDisable() { + this.startSamp = true; + if (this.fpUnWind) { + this.fpUnWind.disabled = false; + } + if (this.recordAccurately) { + this.recordAccurately.disabled = false; + } + if (this.offlineSymbol) { + this.offlineSymbol.disabled = false; + } + if (this.startupMode) { + this.startupMode.disabled = false; + } + this.processId!.removeAttribute('disabled'); + let inputBoxes = this.shadowRoot?.querySelectorAll('.inputBoxes'); + inputBoxes!.forEach((item) =>{ + item.disabled = false; + }) + this.statisticsSlider!.disabled = false; + } + + private disable() { + this.startSamp = false; + if (this.fpUnWind) { + this.fpUnWind.disabled = true; + } + if (this.recordAccurately) { + this.recordAccurately.disabled = true; + } + if (this.startupMode) { + this.startupMode.disabled = true; + } + if (this.offlineSymbol) { + this.offlineSymbol.disabled = true; + } + this.processId!.setAttribute('disabled',''); + let inputBoxes = this.shadowRoot?.querySelectorAll('.inputBoxes'); + inputBoxes!.forEach((item) =>{ + item.disabled = true; + }) + this.statisticsSlider!.disabled = true; } initHtml(): string { @@ -334,7 +406,7 @@ export class SpAllocations extends BaseElement { } .allocation-inputstyle{ background: var(--dark-background5,#FFFFFF); - border: 1px solid var(--dark-background5,#999999); + border: 1px solid var(--dark-background5,#ccc); font-family: Helvetica; font-size: 14px; color: var(--dark-color1,#212121); @@ -342,9 +414,20 @@ export class SpAllocations extends BaseElement { line-height: 16px; font-weight: 400; } - .allocation-inputstyle::-webkit-input-placeholder { - background: var(--dark-background5,#FFFFFF); + + input::-webkit-input-placeholder{ + background: var(--dark-background5,#FFFFFF); + } + + :host([startSamp]) .allocation-inputstyle { + background: var(--dark-background5,#FFFFFF); + } + + :host(:not([startSamp])) .allocation-inputstyle { + color: #b7b7b7; + background: var(--dark-background1,#f5f5f5); } + #one_mb{ background-color:var(--dark-background5, #FFFFFF) } @@ -421,10 +504,28 @@ export class SpAllocations extends BaseElement { color:var(--dark-color,#6a6f77); } + .allocation-title { + opacity: 0.9; + font-family: Helvetica-Bold; + margin-right: 10px; + font-size: 18px; + text-align: center; + line-height: 40px; + font-weight: 700; + } + + lit-switch { + height: 38px; + margin-top: 10px; + display:inline; + float: right; + } +
-
- Native Memory +
+ Start Native Memory Record +
ProcessId or ProcessName @@ -435,13 +536,13 @@ export class SpAllocations extends BaseElement {
Max unwind level Max Unwind Level Rang is 0 - 512, default 10 - +
Shared Memory Size (One page equals 4 KB) Shared Memory Size Range is 0 - 131072 page, default 16384 page
- + Page
@@ -449,7 +550,7 @@ export class SpAllocations extends BaseElement { Filter Memory Size Filter size Range is 0 - 65535 byte, default 4096 byte
- + Byte
@@ -477,7 +578,7 @@ export class SpAllocations extends BaseElement {
- + S
diff --git a/ide/src/trace/component/setting/SpWebHdcShell.ts b/ide/src/trace/component/setting/SpWebHdcShell.ts index 2d659367f509eab6328e983a94eb31b0822eb980..4cf510625cfc0e6c5e0a404d28fc26c095f2766f 100644 --- a/ide/src/trace/component/setting/SpWebHdcShell.ts +++ b/ide/src/trace/component/setting/SpWebHdcShell.ts @@ -168,14 +168,17 @@ export class SpWebHdcShell extends BaseElement { (endY > textLastRowY && endY < textEndY) ) { index++; - if (index == 1) { + if (index === 1) { if (depth > 1) { - selectedText += line.substring(Math.floor((startX - x) / 8)) + (endX < x + w ? '\n' : ''); + selectedText += line.slice( + this.getCurrentLineBackSize(line, startX - x, true)) + (endX < x + w ? '\n' : ''); } else { - selectedText += `${line.substring(Math.floor((startX - x) / 8), Math.ceil((endX - x) / 8))}\n`; + selectedText += `${line.slice( + this.getCurrentLineBackSize(line, startX - x, true), + this.getCurrentLineBackSize(line, endX - x, false))}\n`; } - } else if (index == depth) { - selectedText += `${line.substring(0, Math.ceil((endX - x) / 8))}\n`; + } else if (index === depth) { + selectedText += `${line.slice(0, this.getCurrentLineBackSize(line, endX - x, false))}\n`; } else { selectedText += `${line}\n`; } @@ -229,6 +232,23 @@ export class SpWebHdcShell extends BaseElement { this.points = {startX: startPointX, startY: startPointY, endX: endPointX, endY: endPointY}; } + getCurrentLineBackSize(currentLine: string, maxBackSize: number, isStart: boolean): number{ + let fillText = ''; + let strings = currentLine.split(''); + for (let index = 0; index < strings.length; index++) { + let text = strings[index]; + if (this.shellCanvasCtx!.measureText(fillText).width < maxBackSize && + this.shellCanvasCtx!.measureText(fillText + text).width >= maxBackSize) { + if (!isStart) { + fillText += text; + } + break; + } + fillText += text; + } + return fillText.length; + } + reverseSelected(startX: number, startY: number, endX: number, endY: number): void { //左边界x为SpWebHdcShell.LEFT_OFFSET,右边界为this.shellCanvas!.width let depth = Math.ceil((startY - endY) / 16); @@ -257,6 +277,7 @@ export class SpWebHdcShell extends BaseElement { startPointY = endY; } else { this.shellCanvasCtx!.fillRect(SpWebHdcShell.LEFT_OFFSET, startY - index * 16, this.shellCanvas!.width, 16); + this.shellCanvasCtx!.textBaseline = 'middle'; } } } @@ -320,7 +341,8 @@ export class SpWebHdcShell extends BaseElement { textY = SpWebHdcShell.TOP_OFFSET + index * 16; this.shellCanvasCtx!.fillText(shellStr, SpWebHdcShell.LEFT_OFFSET, textY); } - shellStrLength = this.cursorIndex * unitWidth + SpWebHdcShell.LEFT_OFFSET; + shellStrLength = this.shellCanvasCtx!.measureText( + this.cursorRow.slice(0, this.cursorIndex)).width + SpWebHdcShell.LEFT_OFFSET; if (scroller) { if (textY > this.shellDiv!.clientHeight) { this.shellDiv!.scrollTop = textY - this.shellDiv!.clientHeight + 3; diff --git a/ide/src/trace/component/trace/TimerShaftElement.ts b/ide/src/trace/component/trace/TimerShaftElement.ts index 727870754e12fc1a67539240f249c7c403339fcf..45649810e326c90669ff8304dc38911f8030b014 100644 --- a/ide/src/trace/component/trace/TimerShaftElement.ts +++ b/ide/src/trace/component/trace/TimerShaftElement.ts @@ -123,7 +123,7 @@ export class TimerShaftElement extends BaseElement { canvasHeight: number = 0; _cpuUsage: Array<{ cpu: number; ro: number; rate: number }> = []; protected timeRuler: TimeRuler | undefined; - protected rangeRuler: RangeRuler | undefined; + protected _rangeRuler: RangeRuler | undefined; protected _sportRuler: SportRuler | undefined; private root: HTMLDivElement | undefined | null; private _totalNS: number = 10_000_000_000; @@ -138,11 +138,15 @@ export class TimerShaftElement extends BaseElement { return this._sportRuler; } + get rangeRuler(): RangeRuler | undefined { + return this._rangeRuler; + } + set cpuUsage(value: Array<{ cpu: number; ro: number; rate: number }>) { info('set cpuUsage values :', value); this._cpuUsage = value; - if (this.rangeRuler) { - this.rangeRuler.cpuUsage = this._cpuUsage; + if (this._rangeRuler) { + this._rangeRuler.cpuUsage = this._cpuUsage; } } @@ -154,7 +158,7 @@ export class TimerShaftElement extends BaseElement { info('set totalNS values :', value); this._totalNS = value; if (this.timeRuler) this.timeRuler.totalNS = value; - if (this.rangeRuler) this.rangeRuler.range.totalNS = value; + if (this._rangeRuler) this._rangeRuler.range.totalNS = value; if (this.timeTotalEL) this.timeTotalEL.textContent = `${ns2s(value)}`; requestAnimationFrame(() => this.render()); } @@ -176,7 +180,7 @@ export class TimerShaftElement extends BaseElement { } isScaling(): boolean { - return this.rangeRuler?.isPress || false; + return this._rangeRuler?.isPress || false; } reset(): void { @@ -184,17 +188,17 @@ export class TimerShaftElement extends BaseElement { this.totalNS = 10_000_000_000; this.startNS = 0; this.endNS = 10_000_000_000; - if (this.rangeRuler) { - this.rangeRuler.drawMark = false; - this.rangeRuler.range.totalNS = this.totalNS; - this.rangeRuler.markAObj.frame.x = 0; - this.rangeRuler.markBObj.frame.x = this.rangeRuler.frame.width; - this.rangeRuler.cpuUsage = []; + if (this._rangeRuler) { + this._rangeRuler.drawMark = false; + this._rangeRuler.range.totalNS = this.totalNS; + this._rangeRuler.markAObj.frame.x = 0; + this._rangeRuler.markBObj.frame.x = this._rangeRuler.frame.width; + this._rangeRuler.cpuUsage = []; this.sportRuler!.flagList.length = 0; this.sportRuler!.slicesTimeList.length = 0; this.selectionList.length = 0; this.selectionMap.clear(); - this.rangeRuler.rangeRect = new Rect(0, 25, this.canvas?.clientWidth || 0, 75); + this._rangeRuler.rangeRect = new Rect(0, 25, this.canvas?.clientWidth || 0, 75); this.sportRuler!.isRangeSelect = false; this.setSlicesMark(); } @@ -214,7 +218,7 @@ export class TimerShaftElement extends BaseElement { } getRangeRuler() { - return this.rangeRuler; + return this._rangeRuler; } connectedCallback() { @@ -228,8 +232,8 @@ export class TimerShaftElement extends BaseElement { } } if (this.timeTotalEL) this.timeTotalEL.textContent = ns2s(this._totalNS); - if (this.timeOffsetEL && this.rangeRuler) - this.timeOffsetEL.textContent = ns2UnitS(this._startNS, this.rangeRuler.getScale()); + if (this.timeOffsetEL && this._rangeRuler) + this.timeOffsetEL.textContent = ns2UnitS(this._startNS, this._rangeRuler.getScale()); const width = this.canvas?.clientWidth || 0; const height = this.canvas?.clientHeight || 0; if (!this.timeRuler) { @@ -250,8 +254,8 @@ export class TimerShaftElement extends BaseElement { } ); } - if (!this.rangeRuler) { - this.rangeRuler = new RangeRuler( + if (!this._rangeRuler) { + this._rangeRuler = new RangeRuler( this, new Rect(0, 25, width, 75), { @@ -274,8 +278,8 @@ export class TimerShaftElement extends BaseElement { if (this._sportRuler) { this._sportRuler.range = a; } - if (this.timeOffsetEL && this.rangeRuler) { - this.timeOffsetEL.textContent = ns2UnitS(a.startNS, this.rangeRuler.getScale()); + if (this.timeOffsetEL && this._rangeRuler) { + this.timeOffsetEL.textContent = ns2UnitS(a.startNS, this._rangeRuler.getScale()); } if (this.loadComplete) { this.rangeChangeHandler?.(a); @@ -283,18 +287,18 @@ export class TimerShaftElement extends BaseElement { } ); } - this.rangeRuler.frame.width = width; + this._rangeRuler.frame.width = width; this._sportRuler.frame.width = width; this.timeRuler.frame.width = width; } setRangeNS(startNS: number, endNS: number) { info('set startNS values :' + startNS + 'endNS values : ' + endNS); - this.rangeRuler?.setRangeNS(startNS, endNS); + this._rangeRuler?.setRangeNS(startNS, endNS); } getRange(): TimeRange | undefined { - return this.rangeRuler?.getRange(); + return this._rangeRuler?.getRange(); } updateWidth(width: number) { @@ -309,32 +313,33 @@ export class TimerShaftElement extends BaseElement { this.canvas!.style.height = oldHeight + 'px'; this.ctx?.scale(this.dpr, this.dpr); this.ctx?.translate(0, 0); - this.rangeRuler!.frame.width = oldWidth; + this._rangeRuler!.frame.width = oldWidth; this._sportRuler!.frame.width = oldWidth; this.timeRuler!.frame.width = oldWidth; - this.rangeRuler?.fillX(); + this._rangeRuler?.fillX(); this.render(); } documentOnMouseDown = (ev: MouseEvent) => { if ((window as any).isSheetMove) return; - this.rangeRuler?.mouseDown(ev); + this._rangeRuler?.mouseDown(ev); }; documentOnMouseUp = (ev: MouseEvent) => { if ((window as any).isSheetMove) return; - this.rangeRuler?.mouseUp(ev); + this._rangeRuler?.mouseUp(ev); this.sportRuler?.mouseUp(ev); }; documentOnMouseMove = (ev: MouseEvent, trace: SpSystemTrace) => { trace.style.cursor = 'default'; - let x = ev.offsetX - (this.canvas?.offsetLeft || 0); // 鼠标的x轴坐标 + let x = ev.offsetX - (this.canvas?.offsetLeft || 0); // 鼠标的x轴坐标 let y = ev.offsetY; // 鼠标的y轴坐标 let findSlicestime = this.sportRuler?.findSlicesTime(x, y); // 查找帽子 - if (!findSlicestime) { // 如果在该位置没有找到一个“帽子”,则可以显示一个旗子。 + if (!findSlicestime) { + // 如果在该位置没有找到一个“帽子”,则可以显示一个旗子。 this.sportRuler?.showHoverFlag(); - this.rangeRuler?.mouseMove(ev, trace); + this._rangeRuler?.mouseMove(ev, trace); if (this.sportRuler?.edgeDetection(ev)) { this.sportRuler?.mouseMove(ev); } else { @@ -342,26 +347,26 @@ export class TimerShaftElement extends BaseElement { } } else { this.sportRuler?.clearHoverFlag(); - this.sportRuler?.modifyFlagList(null);//重新绘制旗子,清除hover flag + this.sportRuler?.modifyFlagList(null); //重新绘制旗子,清除hover flag } }; documentOnMouseOut = (ev: MouseEvent) => { - this.rangeRuler?.mouseOut(ev); + this._rangeRuler?.mouseOut(ev); this.sportRuler?.mouseOut(ev); }; documentOnKeyPress = (ev: KeyboardEvent, currentSlicesTime?: CurrentSlicesTime) => { if ((window as any).isSheetMove) return; if ((window as any).flagInputFocus) return; - this.rangeRuler?.keyPress(ev, currentSlicesTime); + this._rangeRuler?.keyPress(ev, currentSlicesTime); this.sportRuler?.clearHoverFlag(); }; documentOnKeyUp = (ev: KeyboardEvent) => { if ((window as any).isSheetMove) return; if ((window as any).flagInputFocus) return; - this.rangeRuler?.keyUp(ev); + this._rangeRuler?.keyUp(ev); }; disconnectedCallback() {} @@ -378,7 +383,7 @@ export class TimerShaftElement extends BaseElement { this.ctx.fillStyle = 'transparent'; this.ctx?.fillRect(0, 0, this.canvas?.width || 0, this.canvas?.height || 0); this.timeRuler?.draw(); - this.rangeRuler?.draw(); + this._rangeRuler?.draw(); this._sportRuler?.draw(); } else { procedurePool.submitWithName( @@ -415,15 +420,15 @@ export class TimerShaftElement extends BaseElement { this._sportRuler?.modifySicesTimeList(slicestime); } cancelPressFrame() { - this.rangeRuler?.cancelPressFrame(); + this._rangeRuler?.cancelPressFrame(); } cancelUpFrame() { - this.rangeRuler?.cancelUpFrame(); + this._rangeRuler?.cancelUpFrame(); } stopWASD(ev: any) { - this.rangeRuler?.keyUp(ev); + this._rangeRuler?.keyUp(ev); } drawTriangle(time: number, type: string) { @@ -455,7 +460,6 @@ export class TimerShaftElement extends BaseElement { return sliceTime; } - displayCollect(showCollect: boolean) { if (showCollect) { this.collecBtn!.style.display = 'flex'; diff --git a/ide/src/trace/component/trace/base/ColorUtils.ts b/ide/src/trace/component/trace/base/ColorUtils.ts index 74e594709f4bd086889a312b42b9bbf8bb6bce2f..fe7cea2de47ea7885eb7efcd099002c1545d941f 100644 --- a/ide/src/trace/component/trace/base/ColorUtils.ts +++ b/ide/src/trace/component/trace/base/ColorUtils.ts @@ -13,12 +13,34 @@ * limitations under the License. */ -import {CpuStruct} from '../../../database/ui-worker/ProcedureWorkerCPU.js'; +import { CpuStruct } from '../../../database/ui-worker/ProcedureWorkerCPU.js'; export class ColorUtils { public static GREY_COLOR: string = '#f0f0f0'; public static FUNC_COLOR_A: Array = [ + '#8770D3', + '#A37775', + '#0CBDD4', + '#7DA6F4', + '#A56DF5', + '#E86B6A', + '#69D3E5', + '#998FE6', + '#E3AA7D', + '#76D1C0', + '#99C47C', + '#DC8077', + '#36BAA4', + '#A1CD94', + '#E68C43', + '#66C7BA', + '#B1CDF1', + '#E7B75D', + '#93D090', + '#ADB7DB', + ]; + public static FUNC_COLOR_B: Array = [ '#40b3e7', '#23b0e7', '#8d9171', @@ -26,6 +48,9 @@ export class ColorUtils { '#7a9160', '#9fafc4', '#8a8a8b', + '#8983B5', + '#78aec2', + '#4ca694', '#e05b52', '#9bb87a', '#ebc247', @@ -33,23 +58,9 @@ export class ColorUtils { '#a16a40', '#a94eb9', '#aa4fba', - ]; - public static FUNC_COLOR_B: Array = [ - '#9785D3', - '#A27F7E', - '#00bdd6', - '#94B5F4', - '#B282F6', - '#E97978', - '#7AD7E6', - '#A1C38A', - '#DB8E86', - '#42B7A4', - '#AACEA0', - '#E69553', - '#7EC6BB', - '#8d9171', - + '#B9A683', + '#789876', + '#8091D0', ]; public static ANIMATION_COLOR: Array = [ @@ -62,7 +73,7 @@ export class ColorUtils { '#BFEBE5', '#0A59F7', '#25ACF5', - '#FFFFFF' + '#FFFFFF', ]; public static JANK_COLOR: Array = [ @@ -194,3 +205,99 @@ export class ColorUtils { } } } +export function interpolateColorBrightness(colorHex: string, percentage: number): number[] { + const color = hexToRgb(colorHex); + if (color.length === 0) { + return []; + } + const [h, s, l] = rgbToHsl(color[0] / 255, color[1] / 255, color[2] / 255); + + // 根据百分比计算亮度插值 + const interpolatedL = 1 - percentage * 0.75; // 百分比越高,亮度越低 + + // 将插值后的亮度值与原始的色相和饱和度值组合 + const interpolatedColor = hslToRgb(h, s, interpolatedL); + const interpolatedColorScaled = interpolatedColor.map((val) => Math.round(val * 255)); + + return interpolatedColorScaled; +} + +function rgbToHsl(r: number, g: number, b: number): number[] { + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); + let h = 0, + s = 0, + l = (max + min) / 2; + + if (max === min) { + h = s = 0; // achromatic + } else { + const d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + + return [h, s, l]; +} + +function hexToRgb(colorHex: string): number[] { + // 16进制颜色值 + const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; + let color = colorHex.toLowerCase(); + if (reg.test(color)) { + // 如果只有三位的值,需变成六位,如:#fff => #ffffff + if (color.length === 4) { + let colorNew = '#'; + for (let i = 1; i < 4; i += 1) { + colorNew += color.slice(i, i + 1).concat(color.slice(i, i + 1)); + } + color = colorNew; + } + // 处理六位的颜色值,转为RGB + let rgb = []; + for (let i = 1; i < 7; i += 2) { + rgb.push(parseInt('0x' + color.slice(i, i + 2))); + } + return rgb; + } + return []; +} + +function hslToRgb(h: number, s: number, l: number): number[] { + let r = 0, + g = 0, + b = 0; + + if (s === 0) { + r = g = b = l; // achromatic + } else { + const hue2rgb = (p: number, q: number, t: number) => { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + }; + + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; + + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + } + + return [r, g, b]; +} diff --git a/ide/src/trace/component/trace/base/CustomThemeColor.ts b/ide/src/trace/component/trace/base/CustomThemeColor.ts new file mode 100644 index 0000000000000000000000000000000000000000..4c882f97ccdb7eeafbc24b69f221f9d398f1bced --- /dev/null +++ b/ide/src/trace/component/trace/base/CustomThemeColor.ts @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BaseElement, element } from '../../../../base-ui/BaseElement.js'; +import { ColorUtils } from './ColorUtils.js'; +import { LitRadioBox } from '../../../../base-ui/radiobox/LitRadioBox.js'; +import { SpApplication } from '../../../SpApplication.js'; + +@element('custom-theme-color') +export class CustomThemeColor extends BaseElement { + private application: SpApplication | undefined | null; + private radios: NodeListOf | undefined | null; + private colorsArray: Array = []; + private colorsEl: HTMLDivElement | undefined | null; + private theme: Theme = Theme.LIGHT; + + static get observedAttributes(): string[] { + return ['mode']; + } + + init(): void { + window.localStorage.getItem('Theme') === 'light' ? (this.theme = Theme.LIGHT) : (this.theme = Theme.DARK); + if (window.localStorage.getItem('Theme') === 'light' || !window.localStorage.getItem('Theme')) { + this.theme = Theme.LIGHT; + } else { + this.theme = Theme.DARK; + } + this.application!.changeTheme(this.theme); + this.setRadioChecked(this.theme); + } + + /** + * 更新色板 + * @param colorsEl 色板的父元素 + */ + createColorsEl(colorsEl: HTMLDivElement) { + for (let i = 0; i < this.colorsArray!.length; i++) { + let div = document.createElement('div'); + div.className = 'color-wrap'; + let input = document.createElement('input'); + input.type = 'color'; + input.className = 'color'; + input.value = this.colorsArray![i]; + div.appendChild(input); + colorsEl?.appendChild(div); + input.addEventListener('change', (evt: any) => { + input.value = evt?.target.value; + this.colorsArray![i] = evt?.target.value; + }); + } + } + + /** + * 根据传入的主题改变color setting页面的单选框状态,更新颜色数组 + * @param theme 主题模式 + */ + setRadioChecked(theme: Theme) { + for (let i = 0; i < this.radios!.length; i++) { + if (this.radios![i].innerHTML === theme) { + this.radios![i].setAttribute('checked', ''); + if (theme === Theme.LIGHT) { + this.colorsArray = + window.localStorage.getItem('LightThemeColors') === null + ? [...ColorUtils.FUNC_COLOR_A] + : JSON.parse(window.localStorage.getItem('LightThemeColors')!); + } else { + this.colorsArray = + window.localStorage.getItem('DarkThemeColors') === null + ? [...ColorUtils.FUNC_COLOR_B] + : JSON.parse(window.localStorage.getItem('DarkThemeColors')!); + } + } else { + this.radios![i].removeAttribute('checked'); + } + } + this.colorsEl!.innerHTML = ''; + this.createColorsEl(this.colorsEl!); + } + + initElements(): void { + this.radios = this.shadowRoot?.querySelectorAll('.litRadio'); + this.colorsEl = this.shadowRoot?.querySelector('.colors') as HTMLDivElement; + this.application = document.querySelector('body > sp-application') as SpApplication; + let close = this.shadowRoot?.querySelector('.page-close'); + if (this.radios) { + for (let i = 0; i < this.radios.length; i++) { + this.radios![i].shadowRoot!.querySelector('.selected')!.classList.add('blue'); + this.radios[i].addEventListener('click', (evt) => { + // 点击颜色模式的单选框,色板切换 + if (this.radios![i].innerHTML === Theme.LIGHT) { + if (this.radios![i].getAttribute('checked') === null) { + this.colorsArray = + window.localStorage.getItem('LightThemeColors') === null + ? [...ColorUtils.FUNC_COLOR_A] + : JSON.parse(window.localStorage.getItem('LightThemeColors')!); + this.theme = Theme.LIGHT; + } else { + return; + } + } else if (this.radios![i].innerHTML === Theme.DARK) { + if (this.radios![i].getAttribute('checked') === null) { + this.colorsArray = + window.localStorage.getItem('DarkThemeColors') === null + ? [...ColorUtils.FUNC_COLOR_B] + : JSON.parse(window.localStorage.getItem('DarkThemeColors')!); + this.theme = Theme.DARK; + } else { + return; + } + } + this.colorsEl!.innerHTML = ''; + this.createColorsEl(this.colorsEl!); + this.confirmOPerate(); + }); + } + } + + close!.addEventListener('click', (ev) => { + if (this.application!.hasAttribute('custom-color')) { + this.application!.removeAttribute('custom-color'); + } + this.cancelOperate(); + }); + let resetBtn = this.shadowRoot?.querySelector('#reset'); + let previewBtn = this.shadowRoot?.querySelector('#preview'); + let confirmBtn = this.shadowRoot?.querySelector('#confirm'); + + resetBtn?.addEventListener('click', () => { + if (this.theme === Theme.LIGHT) { + window.localStorage.setItem('LightThemeColors', JSON.stringify(ColorUtils.FUNC_COLOR_A)); + } else { + window.localStorage.setItem('DarkThemeColors', JSON.stringify(ColorUtils.FUNC_COLOR_B)); + } + this.application!.changeTheme(this.theme); + }); + + previewBtn?.addEventListener('click', () => { + this.application!.changeTheme(this.theme, [...this.colorsArray]); + }); + + confirmBtn?.addEventListener('click', () => { + this.confirmOPerate(); + }); + } + + confirmOPerate() { + window.localStorage.setItem('Theme', this.theme); + if (this.theme === Theme.LIGHT) { + window.localStorage.setItem('LightThemeColors', JSON.stringify([...this.colorsArray])); + } else { + window.localStorage.setItem('DarkThemeColors', JSON.stringify([...this.colorsArray])); + } + this.application!.changeTheme(this.theme); + this.setRadioChecked(this.theme); + } + + cancelOperate() { + if (window.localStorage.getItem('Theme') === 'light' || !window.localStorage.getItem('Theme')) { + this.theme = Theme.LIGHT; + this.colorsArray = + window.localStorage.getItem('LightThemeColors') === null + ? [...ColorUtils.FUNC_COLOR_A] + : JSON.parse(window.localStorage.getItem('LightThemeColors')!); + } else if (window.localStorage.getItem('Theme') === 'dark') { + this.theme = Theme.DARK; + this.colorsArray = + window.localStorage.getItem('DarkThemeColors') === null + ? [...ColorUtils.FUNC_COLOR_B] + : JSON.parse(window.localStorage.getItem('DarkThemeColors')!); + } + this.application!.changeTheme(this.theme); + // 恢复颜色模式单选框checked状态 + this.setRadioChecked(this.theme); + } + + connectedCallback(): void {} + + initHtml(): string { + return ` + +
+
+ Color Setting + +
+
+
+ Appearance + ${Theme.LIGHT} + ${Theme.DARK} +
+
+ Color Customization + Please customize colors according to your preferences +
+
+
+
+
+ + + +
+
+ `; + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string): void { + if (name === 'mode' && newValue === '') { + this.init(); + } + } +} +export enum Theme { + LIGHT = 'light', + DARK = 'dark', +} diff --git a/ide/src/trace/component/trace/base/TraceRowConfig.ts b/ide/src/trace/component/trace/base/TraceRowConfig.ts index c6f0b4f43d9acfdb61035e3b428983fb7030c7f0..d9cd7a67a4f62718e7a7444cc66e856e606c56ea 100644 --- a/ide/src/trace/component/trace/base/TraceRowConfig.ts +++ b/ide/src/trace/component/trace/base/TraceRowConfig.ts @@ -46,16 +46,26 @@ export class TraceRowConfig extends BaseElement { } init(): void { - let sceneList = ['FrameTimeline', 'Task Pool', 'Animation Effect', 'Ark Ts', 'AppStartup']; + let sceneList = [ + 'FrameTimeline', + 'TaskPool', + 'AnimationEffect', + 'AppStartup', + 'HiSysEvent', + 'ProcessMemory', + 'ArkTs', + 'NativeMemory', + 'HiPerf', + 'HiEBpf', + ]; this.selectTypeList = []; this.sceneTable!.innerHTML = ''; this.chartTable!.innerHTML = ''; this.inputElement!.value = ''; this.spSystemTrace = this.parentElement!.querySelector('sp-system-trace'); - this.traceRowList = - this.spSystemTrace!.shadowRoot?.querySelector('div[class=rows-pane]')!.querySelectorAll>( - 'trace-row[row-parent-id=\'\']' - ); + this.traceRowList = this.spSystemTrace!.shadowRoot?.querySelector('div[class=rows-pane]')!.querySelectorAll< + TraceRow + >("trace-row[row-parent-id='']"); let allowSceneList: Array = []; TraceRowConfig.allTraceRowList.push(...this.traceRowList!); this.traceRowList!.forEach((traceRow: TraceRow) => { diff --git a/ide/src/trace/component/trace/search/Search.ts b/ide/src/trace/component/trace/search/Search.ts index 677f9ed6b6d5d6e8cb00934d61281c1c77a9dc03..8846c4151b0f68b10103428085e27969b2e0eb4c 100644 --- a/ide/src/trace/component/trace/search/Search.ts +++ b/ide/src/trace/component/trace/search/Search.ts @@ -15,6 +15,8 @@ import { BaseElement, element } from '../../../../base-ui/BaseElement.js'; +const LOCAL_STORAGE_SEARCH_KEY = 'search_key'; + @element('lit-search') export class LitSearch extends BaseElement { valueChangeHandler: ((str: string) => void) | undefined | null; @@ -24,6 +26,11 @@ export class LitSearch extends BaseElement { private _list: Array = []; private totalEL: HTMLSpanElement | null | undefined; private indexEL: HTMLSpanElement | null | undefined; + private searchHistoryListEL: HTMLUListElement | null | undefined; + private historyMaxCount = 100; + private lastSearch = ''; + private searchList: Array = []; + private searchELList: Array = []; get list(): Array { return this._list; @@ -52,7 +59,12 @@ export class LitSearch extends BaseElement { } set total(value: number) { - value > 0 ? this.setAttribute('show-search-info', '') : this.removeAttribute('show-search-info'); + if (value > 0) { + this.setAttribute('show-search-info', ''); + this.updateSearchList(this.search!.value); + } else { + this.removeAttribute('show-search-info'); + } this._total = value; this.totalEL!.textContent = value.toString(); } @@ -66,6 +78,7 @@ export class LitSearch extends BaseElement { this.setAttribute('isLoading', ''); } else { this.removeAttribute('isLoading'); + window.localStorage.setItem(LOCAL_STORAGE_SEARCH_KEY, ''); } } @@ -123,57 +136,104 @@ export class LitSearch extends BaseElement { this.search?.blur(); } + updateSearchList(searchStr: string | null) { + if (searchStr === null || searchStr.length === 0 || searchStr.trim().length === 0) { + return; + } + if (this.lastSearch === searchStr) { + return; + } + this.lastSearch = searchStr; + let searchInfo = this.searchList.find(searchInfo => searchInfo.searchContent === searchStr); + if (searchInfo != undefined) { + searchInfo.useCount += 1; + } else { + this.searchList.push({searchContent: searchStr, useCount: 1}); + } + } + + getSearchHistory(): Array { + let searchString = window.localStorage.getItem(LOCAL_STORAGE_SEARCH_KEY); + if (searchString) { + let searHistory = JSON.parse(searchString); + if (Array.isArray(searHistory)) { + this.searchList = searHistory; + return searHistory; + } + } + return []; + } + + private searchFocusListener() { + if (!this.search?.hasAttribute('readonly')) { + this.showSearchHistoryList(); + } + this.dispatchEvent( + new CustomEvent('focus', { + detail: { + value: this.search!.value, + }, + }) + ); + } + + private searchBlurListener() { + this.dispatchEvent( + new CustomEvent('blur', { + detail: { + value: this.search!.value, + }, + }) + ); + setTimeout(() => { + this.hideSearchHistoryList(); + }, 200); + } + + private searchKeyupListener(e: KeyboardEvent) { + if (e.code == 'Enter') { + if (e.shiftKey) { + this.dispatchEvent( + new CustomEvent('previous-data', { + detail: { + value: this.search!.value, + }, + composed: false, + }) + ); + } else { + this.dispatchEvent( + new CustomEvent('next-data', { + detail: { + value: this.search!.value, + }, + composed: false, + }) + ); + } + } else { + this.updateSearchHistoryList(this.search!.value); + this.valueChangeHandler?.(this.search!.value); + } + e.stopPropagation(); + } + initElements(): void { this.search = this.shadowRoot!.querySelector('input'); this.totalEL = this.shadowRoot!.querySelector('#total'); this.indexEL = this.shadowRoot!.querySelector('#index'); - this.search!.addEventListener('focus', (e) => { - this.dispatchEvent( - new CustomEvent('focus', { - detail: { - value: this.search!.value, - }, - }) - ); + this.searchHistoryListEL = this.shadowRoot!.querySelector('.search-history-list'); + this.search!.addEventListener('focus', () => { + this.searchFocusListener(); }); this.search!.addEventListener('blur', (e) => { - this.dispatchEvent( - new CustomEvent('blur', { - detail: { - value: this.search!.value, - }, - }) - ); + this.searchBlurListener(); }); this.search!.addEventListener('change', (event) => { this.index = -1; }); - this.search!.addEventListener('keyup', (e: KeyboardEvent) => { - if (e.code == 'Enter') { - if (e.shiftKey) { - this.dispatchEvent( - new CustomEvent('previous-data', { - detail: { - value: this.search!.value, - }, - composed: false, - }) - ); - } else { - this.dispatchEvent( - new CustomEvent('next-data', { - detail: { - value: this.search!.value, - }, - composed: false, - }) - ); - } - } else { - this.valueChangeHandler?.(this.search!.value); - } - e.stopPropagation(); + this.searchKeyupListener(e); }); this.shadowRoot?.querySelector('#arrow-left')?.addEventListener('click', (e) => { this.dispatchEvent( @@ -213,6 +273,7 @@ export class LitSearch extends BaseElement { } .root input{ outline: none; + width: max-content; border: 0px; background-color: transparent; font-size: inherit; @@ -222,7 +283,7 @@ export class LitSearch extends BaseElement { vertical-align:middle; line-height:inherit; height:inherit; - padding: 6px 6px 6px 6px}; + padding: 6px 6px 6px 6px; max-height: inherit; box-sizing: border-box; } @@ -272,8 +333,29 @@ export class LitSearch extends BaseElement { 100% { left: 100%; } + } + .search-history { + position: relative; + } + .search-history-list { + list-style-type: none; + margin: 0; + position: absolute; + width: 35vw; + top: 100%; + background-color: #FFFFFF; + border: 1px solid #ddd; + max-height: 200px; + overflow-y: auto; + display: none; + border-radius: 0 0 20px 20px; } - + .search-history-list-item { + cursor: pointer; + } + .search-history-list-item:hover { + background-color: #e9e9e9; + }
+
+
    +
    `; } + + showSearchHistoryList() { + this.searchHistoryListEL!.innerHTML = ''; + let historyInfos = this.getSearchHistory(); + let fragment = new DocumentFragment(); + historyInfos.forEach((historyInfo) => { + let searchInfoOption = document.createElement('li'); + searchInfoOption.className = 'search-history-list-item'; + searchInfoOption.textContent = historyInfo.searchContent; + searchInfoOption.addEventListener('click', () => { + if (searchInfoOption.textContent) { + this.search!.value = searchInfoOption.textContent; + this.valueChangeHandler?.(this.search!.value); + } + }); + this.searchELList.push(searchInfoOption); + fragment.append(searchInfoOption); + }); + this.searchHistoryListEL?.append(fragment); + this.searchHistoryListEL!.style.display = 'block'; + } + + hideSearchHistoryList() { + this.searchHistoryListEL!.style.display = 'none'; + this.searchList = this.searchList.sort((a, b) => { + return b.useCount - a.useCount; + }); + if (this.searchList.length > this.historyMaxCount) { + this.searchList = this.searchList.slice(0, this.historyMaxCount); + } + if (this.searchList.length === 0) { + return; + } + let historyStr = JSON.stringify(this.searchList); + window.localStorage.setItem(LOCAL_STORAGE_SEARCH_KEY, historyStr); + this.searchList = []; + this.searchELList = []; + } + + updateSearchHistoryList(searchValue: string) { + const keyword = searchValue.toLowerCase(); + this.searchELList.forEach(item => { + if (item.textContent!.toLowerCase().includes(keyword)) { + item.style.display = 'block'; + } else { + item.style.display = 'none'; + } + }); + } + +} + +export interface SearchInfo { + searchContent: string + useCount: number } diff --git a/ide/src/trace/component/trace/sheet/SheetUtils.ts b/ide/src/trace/component/trace/sheet/SheetUtils.ts index 243bc7e19fc09f761492427cfaa1736f890088d0..216cb0e544b1bc2edc0ff6254ace95b805484c9b 100644 --- a/ide/src/trace/component/trace/sheet/SheetUtils.ts +++ b/ide/src/trace/component/trace/sheet/SheetUtils.ts @@ -14,6 +14,7 @@ */ import { LitTable } from '../../../../base-ui/table/lit-table.js'; +import { NativeMemoryExpression } from '../../../bean/NativeHook.js'; export function resizeObserver( parentEl: HTMLElement, @@ -106,7 +107,9 @@ export class CompareStruct { export class ParseExpression { private expression: string; //输入的表达式 private libTreeMap: Map = new Map(); + private expressionStruct: NativeMemoryExpression; constructor(expression: string) { + this.expressionStruct = new NativeMemoryExpression(); this.expression = expression.trim(); } @@ -114,7 +117,7 @@ export class ParseExpression { * 解析用户输入的表达式 * @returns string:sql/ null: 非法表达式 */ - public parse(): Map | null { + public parse(): NativeMemoryExpression | null { // 表达式必须以@开头 if (!this.expression.startsWith('@')) { return null; @@ -136,7 +139,7 @@ export class ParseExpression { this.paseSingleExpression(expression, include); include = false; } - return this.libTreeMap; + return this.expressionStruct; } private paseSingleExpression(expression: string, includes: boolean): void { @@ -156,9 +159,9 @@ export class ParseExpression { continue; } if (includes) { - this.libTreeMap.set(`+${path}`, items); + this.expressionStruct.includeLib.set(`${path}`, items); } else { - this.libTreeMap.set(`-${path}`, items); + this.expressionStruct.abandonLib.set(`${path}`, items); } } } diff --git a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts index 436c92a158f00ea80ae60eadc9b523b0f67d60dd..fd0775654e01ab7702f6b94583e3ac8b8e28008e 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts @@ -200,7 +200,7 @@ export class TabPaneCurrentSelection extends BaseElement { cpu: data.cpu, dur: data.dur, priority: data.priority, - isSelected: false + isSelected: false, }; this.weakUpBean = bean; @@ -1064,15 +1064,9 @@ export class TabPaneCurrentSelection extends BaseElement { wb = wf[0]; if (wb !== null) { wb.wakeupTime = wakeupTs - recordStartTs; - wb.process = Utils.PROCESS_MAP.get(wb.pid!); - wb.thread = Utils.THREAD_MAP.get(wb.tid!); + wb.process = Utils.PROCESS_MAP.get(wb.pid!) || 'Process'; + wb.thread = Utils.THREAD_MAP.get(wb.tid!) || 'Thread'; wb.schedulingLatency = (data.startTime || 0) - (wb.wakeupTime || 0); - if (wb.process === null) { - wb.process = wb.thread; - } - if (wb.pid === undefined) { - wb.pid = wb.tid; - } wb.schedulingDesc = INPUT_WORD; } } @@ -1095,15 +1089,9 @@ export class TabPaneCurrentSelection extends BaseElement { wb = wf[0]; if (wb !== null) { wb.wakeupTime = wakeupTs - recordStartTs; - wb.process = Utils.PROCESS_MAP.get(wb.pid!); - wb.thread = Utils.THREAD_MAP.get(wb.tid!); + wb.process = Utils.PROCESS_MAP.get(wb.pid!) || 'Process'; + wb.thread = Utils.THREAD_MAP.get(wb.tid!) || 'Thread'; wb.schedulingLatency = (data.ts || 0) - (wb.wakeupTime || 0); - if (wb.process === null) { - wb.process = wb.thread; - } - if (wb.pid === undefined) { - wb.pid = wb.tid; - } wb.schedulingDesc = INPUT_WORD; } } @@ -1232,45 +1220,47 @@ export class TabPaneCurrentSelection extends BaseElement { this.wakeupListTbl = this.shadowRoot?.querySelector('#wakeupListTbl'); this.scrollView = this.shadowRoot?.querySelector('#scroll_view'); this.currentSelectionTbl?.addEventListener('column-click', (ev: any) => {}); - window.subscribe(window.SmartEvent.UI.WakeupList, (data: Array) => { - this.wakeupListTbl!.style.display = 'flex'; - let cpus: number[] = [] - let itids: number[] = [] - let ts: number[] = [] - let maxPriority = 0; - let maxDuration = 0; - data.forEach(it => { - cpus.push(it.cpu!); - itids.push(it.itid!); - ts.push(it.ts!); - }); - queryWakeupListPriority(itids,ts,cpus).then(res => { - let resource = data.map(it => { - let wake = { - process: `${it.process}(${it.pid})`, - thread: `${it.thread}(${it.tid})`, - cpu: it.cpu, - dur: it.dur, - priority: 0, - isSelected: false - }; - let find = res.find(re => re.cpu === it.cpu && re.itid === it.itid && re.ts === it.ts); - if (find) { - wake.priority = find.priority; - } - maxDuration = Math.max(maxDuration, it.dur!); - maxPriority = Math.max(maxPriority, wake.priority); - return wake; - }); - if (this.selectWakeupBean) { - resource.unshift(this.selectWakeupBean); + window.subscribe(window.SmartEvent.UI.WakeupList, (data: Array) => this.showWakeupListTableData(data)); + } + + showWakeupListTableData(data: Array) { + this.wakeupListTbl!.style.display = 'flex'; + let cpus: number[] = []; + let itids: number[] = []; + let ts: number[] = []; + let maxPriority = 0; + let maxDuration = 0; + data.forEach((it) => { + cpus.push(it.cpu!); + itids.push(it.itid!); + ts.push(it.ts!); + }); + queryWakeupListPriority(itids, ts, cpus).then((res) => { + let resource = data.map((it) => { + let wake = { + process: `${it.process}(${it.pid})`, + thread: `${it.thread}(${it.tid})`, + cpu: it.cpu, + dur: it.dur, + priority: 0, + isSelected: false, + }; + let find = res.find((re) => re.cpu === it.cpu && re.itid === it.itid && re.ts === it.ts); + if (find) { + wake.priority = find.priority; } - resource.forEach(it => { - it.isSelected = it.priority === maxPriority || it.dur === maxDuration; - }); - this.wakeupListTbl!.recycleDataSource = resource; + maxDuration = Math.max(maxDuration, it.dur!); + maxPriority = Math.max(maxPriority, wake.priority); + return wake; }); - }) + if (this.selectWakeupBean) { + resource.unshift(this.selectWakeupBean); + } + resource.forEach((it) => { + it.isSelected = it.priority === maxPriority || it.dur === maxDuration; + }); + this.wakeupListTbl!.recycleDataSource = resource; + }); } addTableObserver(): void { diff --git a/ide/src/trace/component/trace/sheet/ark-ts/TabPaneJsCpu.ts b/ide/src/trace/component/trace/sheet/ark-ts/TabPaneJsCpu.ts index 83279641becfaafd2b6c90e485dea0c97d82a604..ca93f7c15a7f17cae60042b949d5af9836d56d53 100644 --- a/ide/src/trace/component/trace/sheet/ark-ts/TabPaneJsCpu.ts +++ b/ide/src/trace/component/trace/sheet/ark-ts/TabPaneJsCpu.ts @@ -35,9 +35,10 @@ export class TabPaneJsCpuCallTree extends BaseElement { private profilerFilter: TabPaneFilter | undefined | null; private searchValue: string = ''; private totalNs: number = 0; + private currentSelection: SelectionParam | undefined; private getDataByWorker(args: Array, handler: Function): void { const key = this.currentType === this.TYPE_TOP_DOWN ? 'jsCpuProfiler-call-tree' : 'jsCpuProfiler-bottom-up'; - this.callTreeTable!.mode = TableMode.Retract; + this.callTreeTable!.mode = TableMode.Retract; procedurePool.submitWithName('logic1', key, args, undefined, (results: Array) => { handler(results); }); @@ -45,8 +46,11 @@ export class TabPaneJsCpuCallTree extends BaseElement { set data(data: SelectionParam | Array) { if (data instanceof SelectionParam) { + if (data == this.currentSelection) { + return; + } + this.currentSelection = data; let chartData = []; - chartData = data.jsCpuProfilerData; this.totalNs = chartData.reduce((acc, struct) => acc + struct.totalTime, 0); if (data.rightNs && data.leftNs) { @@ -285,7 +289,7 @@ export class TabPaneJsCpuCallTree extends BaseElement {
    - + diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuStateClick.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuStateClick.ts index b7d9a98fa05f782f344b2887043e9f2098fecde7..56a8f5c6c1db9d09f4b5910a1c35a3bdc003a323 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuStateClick.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuStateClick.ts @@ -24,7 +24,7 @@ export class TabPaneCpuStateClick extends BaseElement { set data(cpuStateClickValue: any) { if (cpuStateClickValue) { - this.cpuStateClickTbl!.dataSource = [ + this.cpuStateClickTbl!.recycleDataSource = [ { startNS: Utils.getTimeString(cpuStateClickValue.startTs), absoluteTime: (cpuStateClickValue.startTs + (window as any).recordStartNS) / 1000000000, diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts b/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts index d74e081c0d20d6a97f534c04ca7c5387d9c8350d..418a0855a0aee55a12c6907ecda6bddbbb82f0c4 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts @@ -14,7 +14,7 @@ */ import { BaseElement, element } from '../../../../../base-ui/BaseElement.js'; -import { LitTable } from '../../../../../base-ui/table/lit-table.js'; +import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table.js'; import { SelectionParam } from '../../../../bean/BoxSelection.js'; import { resizeObserver } from '../SheetUtils.js'; import { procedurePool } from '../../../../database/Procedure.js'; @@ -48,14 +48,40 @@ export class TabPanePTS extends BaseElement { procedurePool.submitWithName( 'logic1', 'spt-getPTS', - { leftNs: ptsLeftNs, rightNs: ptsRightNs, cpus: cpus}, + { leftNs: ptsLeftNs, rightNs: ptsRightNs, cpus: cpus }, undefined, (res: Array) => { this.ptsTbl!.loading = false; this.ptsTbl!.recycleDataSource = res; + this.theadClick(res); } ); } + private theadClick(data: Array) { + let labels = this.ptsTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); + if (labels) { + for (let i = 0; i < labels.length; i++) { + let label = labels[i].innerHTML; + labels[i].addEventListener('click', (e) => { + if (label.includes('Process') && i === 0) { + this.ptsTbl!.setStatus(data, false); + this.ptsTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('Thread') && i === 1) { + for (let item of data) { + item.status = true; + if (item.children != undefined && item.children.length > 0) { + this.ptsTbl!.setStatus(item.children, false); + } + } + this.ptsTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('State') && i === 2) { + this.ptsTbl!.setStatus(data, true); + this.ptsTbl!.meauseTreeRowElement(data, RedrawTreeForm.Expand); + } + }); + } + } + } connectedCallback() { super.connectedCallback(); @@ -71,7 +97,7 @@ export class TabPanePTS extends BaseElement { - + diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts index 8e958ba601ddfc606d8635c6ac9d99412a6a8b9c..ca69912816fe18ab2f56c398ad7a5f8bc6e80784 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts @@ -14,7 +14,7 @@ */ import { BaseElement, element } from '../../../../../base-ui/BaseElement.js'; -import { LitTable } from '../../../../../base-ui/table/lit-table.js'; +import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table.js'; import { SelectionParam } from '../../../../bean/BoxSelection.js'; import { SliceGroup } from '../../../../bean/StateProcessThread.js'; import { resizeObserver } from '../SheetUtils.js'; @@ -60,10 +60,37 @@ export class TabPaneSPT extends BaseElement { (res: Array) => { this.sptTbl!.loading = false; this.sptTbl!.recycleDataSource = res; + this.theadClick(res); } ); } + private theadClick(data: Array) { + let labels = this.sptTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); + if (labels) { + for (let i = 0; i < labels.length; i++) { + let label = labels[i].innerHTML; + labels[i].addEventListener('click', (e) => { + if (label.includes('State') && i === 0) { + this.sptTbl!.setStatus(data, false); + this.sptTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('Process') && i === 1) { + for (let item of data) { + item.status = true; + if (item.children != undefined && item.children.length > 0) { + this.sptTbl!.setStatus(item.children, false); + } + } + this.sptTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('Thread') && i === 2) { + this.sptTbl!.setStatus(data, true); + this.sptTbl!.meauseTreeRowElement(data, RedrawTreeForm.Expand); + } + }); + } + } + } + initHtml(): string { return ` - + diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts index e283c52181bfed68dc9d00ad90abd4516d2dd473..9e664269249b216f5eb2d1c22ec5f83c84ba2e6d 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts @@ -14,7 +14,7 @@ */ import { BaseElement, element } from '../../../../../base-ui/BaseElement.js'; -import { LitTable } from '../../../../../base-ui/table/lit-table.js'; +import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table.js'; import { SelectionParam } from '../../../../bean/BoxSelection.js'; import { resizeObserver } from '../SheetUtils.js'; import { procedurePool } from '../../../../database/Procedure.js'; @@ -27,6 +27,7 @@ export class TabPaneSchedPriority extends BaseElement { private priorityTbl: LitTable | null | undefined; private range: HTMLLabelElement | null | undefined; private selectionParam: SelectionParam | null | undefined; + private strValueMap: Map = new Map(); set data(sptValue: SelectionParam) { if (sptValue == this.selectionParam) { @@ -53,96 +54,124 @@ export class TabPaneSchedPriority extends BaseElement { private async queryDataByDB(sptParam: SelectionParam | any): Promise { this.priorityTbl!.loading = true; const resultData: Array = []; - const strValueMap: Map = new Map(); - await queryThreadStateArgsByName('next_info').then((value) => { - for (const item of value) { - strValueMap.set(item.argset, item.strValue); - } - }); - procedurePool.submitWithName('logic1', 'spt-getCpuPriority', {}, undefined, async (res: Array) => { - for (const item of res) { - if (item.cpu === null || !(sptParam.cpus.includes(item.cpu))) { - continue; + if (this.strValueMap.size === 0){ + await queryThreadStateArgsByName('next_info').then((value) => { + for (const item of value) { + this.strValueMap.set(item.argset, item.strValue); } - if (!(item.endTs < sptParam.leftNs || item.startTs > sptParam.rightNs)) { + }); + } + + const filterList = ['0', '0x0']; //next_info第2字段不为0 || next_info第3字段不为0 + + // 通过priority与next_info结合判断优先级等级 + function setPriority(item: Priority, strArg: string[]) { + if (item.priority >= 0 && item.priority <= 88) { + item.priorityType = 'RT'; + } else if (item.priority >= 89 && item.priority <= 99) { + item.priorityType = 'VIP2.0'; + } else if ( + item.priority >= 100 && + strArg.length > 1 && + (!filterList.includes(strArg[1]) || !filterList.includes(strArg[2])) + ) { + item.priorityType = 'STATIC_VIP'; + } else { + item.priorityType = 'CFS'; + } + } + // thread_state表中runnable数据的Map + const runnableMap = new Map(); + procedurePool.submitWithName( + 'logic1', + 'spt-getCpuPriorityByTime', + { leftNs: sptParam.leftNs, rightNs: sptParam.rightNs }, + undefined, + async (res: Array) => { + for (const item of res) { + if (['R', 'R+'].includes(item.state)) { + runnableMap.set(`${item.itid}_${item.endTs}`, item); + } + if (item.cpu === null || !sptParam.cpus.includes(item.cpu)) { + continue; + } + let strArg: string[] = []; - const args = strValueMap.get(item.argSetID); + const args = this.strValueMap.get(item.argSetID); if (args) { strArg = args!.split(','); } - const filterList = ['0', '0x0']; + const slice = Utils.SCHED_SLICE_MAP.get(`${item.itId}-${item.startTs}`); if (slice) { - item.priority = slice!.priority; - item.endState = slice.endState; - if (item.priority >= 0 && item.priority <= 88) { - item.priorityType = 'RT'; - } else if (item.priority >= 89 && item.priority <= 99) { - item.priorityType = 'VIP2.0'; - } else if ( - item.priority >= 100 && - strArg.length > 1 && - (!filterList.includes(strArg[1]) || !filterList.includes(strArg[2])) - ) { - item.priorityType = 'STATIC_VIP'; - } else { - item.priorityType = 'CFS'; + const runningPriority = new Priority(); + runningPriority.priority = slice.priority; + runningPriority.state = 'Running'; + runningPriority.dur = item.dur; + setPriority(runningPriority, strArg); + resultData.push(runningPriority); + + const runnableItem = runnableMap.get(`${item.itid}_${item.startTs}`); + if (runnableItem) { + const runnablePriority = new Priority(); + runnablePriority.priority = slice.priority; + runnablePriority.state = 'Runnable'; + runnablePriority.dur = runnableItem.dur; + setPriority(runnablePriority, strArg); + resultData.push(runnablePriority); } - resultData.push(item); } - } else { - continue; } + this.getDataByPriority(resultData); } - this.getDataByPriority(resultData); - }); + ); } private getDataByPriority(source: Array): void { const priorityMap: Map = new Map(); const stateMap: Map = new Map(); - source.map((d) => { - if (priorityMap.has(d.priorityType + '')) { - const priorityMapObj = priorityMap.get(d.priorityType + ''); + source.map((priorityItem) => { + if (priorityMap.has(priorityItem.priorityType + '')) { + const priorityMapObj = priorityMap.get(priorityItem.priorityType + ''); priorityMapObj!.count++; - priorityMapObj!.wallDuration += d.dur; + priorityMapObj!.wallDuration += priorityItem.dur; priorityMapObj!.avgDuration = (priorityMapObj!.wallDuration / priorityMapObj!.count).toFixed(2); - if (d.dur > priorityMapObj!.maxDuration) { - priorityMapObj!.maxDuration = d.dur; + if (priorityItem.dur > priorityMapObj!.maxDuration) { + priorityMapObj!.maxDuration = priorityItem.dur; } - if (d.dur < priorityMapObj!.minDuration) { - priorityMapObj!.minDuration = d.dur; + if (priorityItem.dur < priorityMapObj!.minDuration) { + priorityMapObj!.minDuration = priorityItem.dur; } } else { const stateMapObj = new Priority(); - stateMapObj.title = d.priorityType; - stateMapObj.minDuration = d.dur; - stateMapObj.maxDuration = d.dur; + stateMapObj.title = priorityItem.priorityType; + stateMapObj.minDuration = priorityItem.dur; + stateMapObj.maxDuration = priorityItem.dur; stateMapObj.count = 1; - stateMapObj.avgDuration = d.dur + ''; - stateMapObj.wallDuration = d.dur; - priorityMap.set(d.priorityType + '', stateMapObj); + stateMapObj.avgDuration = priorityItem.dur + ''; + stateMapObj.wallDuration = priorityItem.dur; + priorityMap.set(priorityItem.priorityType + '', stateMapObj); } - if (stateMap.has(d.priorityType + '_' + d.endState)) { - const ptsPtMapObj = stateMap.get(d.priorityType + '_' + d.endState); + if (stateMap.has(priorityItem.priorityType + '_' + priorityItem.state)) { + const ptsPtMapObj = stateMap.get(priorityItem.priorityType + '_' + priorityItem.state); ptsPtMapObj!.count++; - ptsPtMapObj!.wallDuration += d.dur; + ptsPtMapObj!.wallDuration += priorityItem.dur; ptsPtMapObj!.avgDuration = (ptsPtMapObj!.wallDuration / ptsPtMapObj!.count).toFixed(2); - if (d.dur > ptsPtMapObj!.maxDuration) { - ptsPtMapObj!.maxDuration = d.dur; + if (priorityItem.dur > ptsPtMapObj!.maxDuration) { + ptsPtMapObj!.maxDuration = priorityItem.dur; } - if (d.dur < ptsPtMapObj!.minDuration) { - ptsPtMapObj!.minDuration = d.dur; + if (priorityItem.dur < ptsPtMapObj!.minDuration) { + ptsPtMapObj!.minDuration = priorityItem.dur; } } else { const ptsPtMapObj = new Priority(); - ptsPtMapObj.title = Utils.getEndState(d.endState); - ptsPtMapObj.minDuration = d.dur; - ptsPtMapObj.maxDuration = d.dur; + ptsPtMapObj.title = priorityItem.state; + ptsPtMapObj.minDuration = priorityItem.dur; + ptsPtMapObj.maxDuration = priorityItem.dur; ptsPtMapObj.count = 1; - ptsPtMapObj.avgDuration = d.dur + ''; - ptsPtMapObj.wallDuration = d.dur; - stateMap.set(d.priorityType + '_' + d.endState, ptsPtMapObj); + ptsPtMapObj.avgDuration = priorityItem.dur + ''; + ptsPtMapObj.wallDuration = priorityItem.dur; + stateMap.set(priorityItem.priorityType + '_' + priorityItem.state, ptsPtMapObj); } }); @@ -160,6 +189,25 @@ export class TabPaneSchedPriority extends BaseElement { } this.priorityTbl!.loading = false; this.priorityTbl!.recycleDataSource = priorityArr; + this.theadClick(priorityArr); + } + + private theadClick(data: Array) { + let labels = this.priorityTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); + if (labels) { + for (let i = 0; i < labels.length; i++) { + let label = labels[i].innerHTML; + labels[i].addEventListener('click', (e) => { + if (label.includes('Priority') && i === 0) { + this.priorityTbl!.setStatus(data, false); + this.priorityTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('State') && i === 1) { + this.priorityTbl!.setStatus(data, true); + this.priorityTbl!.meauseTreeRowElement(data, RedrawTreeForm.Expand); + } + }); + } + } } public initHtml(): string { @@ -173,7 +221,7 @@ export class TabPaneSchedPriority extends BaseElement { - + diff --git a/ide/src/trace/component/trace/sheet/file-system/TabPaneCallTree.ts b/ide/src/trace/component/trace/sheet/file-system/TabPaneCallTree.ts index bb6a6c09d4dc367ab537fd3f5475a95a373fa7e6..c9f27989c2b1b4e040ffbbbfe60e84fb52690c5e 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneCallTree.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneCallTree.ts @@ -223,8 +223,8 @@ export class TabPaneCallTree extends BaseElement { // @ts-ignore let data = evt.detail.data as MerageBean; document.dispatchEvent( - new CustomEvent('triangle-flag', { - detail: { time: data.tsArray, type: 'triangle' }, + new CustomEvent('number_calibration', { + detail: { time: data.tsArray, durations: data.durArray}, }) ); this.setRightTableData(data); @@ -457,7 +457,9 @@ export class TabPaneCallTree extends BaseElement { this.isChartShow = true; this.callTreeFilter!.disabledMining = true; showButtonMenu(this.callTreeFilter, this.needShowMenu); - if (!data) this.frameChart!.data = this.callTreeDataSource; + if (!data){ + this.frameChart!.data = this.callTreeDataSource; + } this.frameChart?.calculateChartData(); } else if (data.icon === 'tree') { callTreePageChart?.setAttribute('class', ''); @@ -603,7 +605,7 @@ export class TabPaneCallTree extends BaseElement {
    - + diff --git a/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.ts b/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.ts index b4b4eda9b53423db85ff60151c0a4e4fee05cfe6..a46556b58eaa43c98659d38b788146baff2ce76d 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.ts @@ -86,6 +86,7 @@ export class TabpaneFilesystemCalltree extends BaseElement { this.frameChart?.updateCanvas(true, this.clientWidth); this.frameChart?.calculateChartData(); this.switchFlameChart(); + this.fsCallTreeFilter.icon = 'block'; } ); } @@ -173,8 +174,8 @@ export class TabpaneFilesystemCalltree extends BaseElement { // @ts-ignore let data = evt.detail.data as FileMerageBean; document.dispatchEvent( - new CustomEvent('triangle-flag', { - detail: { time: data.tsArray, type: 'triangle' }, + new CustomEvent('number_calibration', { + detail: { time: data.tsArray,durations: data.durArray }, }) ); this.setRightTableData(data); @@ -595,7 +596,7 @@ export class TabpaneFilesystemCalltree extends BaseElement {
    - + diff --git a/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.ts b/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.ts index 8b72134e0fa07c041693bf1705611616d8a6c015..13201706eb650a265d6fbb84076514825132a3f7 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.ts @@ -215,7 +215,7 @@ export class TabPaneFileStatistics extends BaseElement { } - + diff --git a/ide/src/trace/component/trace/sheet/file-system/TabPaneIOTierStatistics.ts b/ide/src/trace/component/trace/sheet/file-system/TabPaneIOTierStatistics.ts index 7ddeae68cfb3f2b600d8f7060c9c78098003f52a..6562632a1d4230db44e2bfa4897232b8ca6bfa77 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneIOTierStatistics.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneIOTierStatistics.ts @@ -276,7 +276,7 @@ export class TabPaneIOTierStatistics extends BaseElement { } - + diff --git a/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.ts b/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.ts index 661d35b79c4b76584a29a0c19cd82ae07cd5b6ba..1441162613d3c5dd89fe195d14cfdd8b88893058 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.ts @@ -291,7 +291,7 @@ export class TabPaneVirtualMemoryStatistics extends BaseElement { } - + diff --git a/ide/src/trace/component/trace/sheet/freq/TabPaneFreq.ts b/ide/src/trace/component/trace/sheet/freq/TabPaneFreq.ts index a2b16feab2f0daf40344f72fb1d0e61755770bdd..3c37d3d3d6060e141f090e547d98b8f7bbb5d58e 100644 --- a/ide/src/trace/component/trace/sheet/freq/TabPaneFreq.ts +++ b/ide/src/trace/component/trace/sheet/freq/TabPaneFreq.ts @@ -25,7 +25,7 @@ export class TabPaneFreq extends BaseElement { set data(freqData: any) { if (freqData) { - this.freqTbl!.dataSource = [ + this.freqTbl!.recycleDataSource = [ { startNS: Utils.getTimeString(freqData.startNS >= 0 ? freqData.startNS : 0), absoluteTime: (freqData.startNS + (window as any).recordStartNS) / 1000000000, diff --git a/ide/src/trace/component/trace/sheet/freq/TabPaneFreqLimit.ts b/ide/src/trace/component/trace/sheet/freq/TabPaneFreqLimit.ts index a12ddfc3cfb41ba110ebcc24149b40dc87b82b45..0c96423c1befd016b88e01c94e855c6105683818 100644 --- a/ide/src/trace/component/trace/sheet/freq/TabPaneFreqLimit.ts +++ b/ide/src/trace/component/trace/sheet/freq/TabPaneFreqLimit.ts @@ -25,7 +25,7 @@ export class TabPaneFreqLimit extends BaseElement { set data(freqLimit: any) { if (freqLimit) { - this.freqLimitTbl!.dataSource = [ + this.freqLimitTbl!.recycleDataSource = [ { startNs: Utils.getTimeString(freqLimit.startNs >= 0 ? freqLimit.startNs : 0), absoluteTime: (freqLimit.startNs + (window as any).recordStartNS) / 1000000000, diff --git a/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts b/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts index bded913a05639e4fb82dfca85fc9e6384e291741..ed6752503eb81b78dcbe7d52753fafdafd69e194 100644 --- a/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts +++ b/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts @@ -18,6 +18,7 @@ import { SelectionParam } from '../../../../bean/BoxSelection.js'; import { LogStruct } from '../../../../database/ui-worker/ProcedureWorkerLog.js'; import { ColorUtils } from '../../base/ColorUtils.js'; import { LitTable } from '../../../../../base-ui/table/lit-table.js'; +import { LitIcon } from '../../../../../base-ui/icon/LitIcon.js'; @element('tab-hi-log-summary') export class TabPaneHiLogSummary extends BaseElement { @@ -25,8 +26,13 @@ export class TabPaneHiLogSummary extends BaseElement { private summaryDownLoadTbl: LitTable | undefined | null; private parentTabEl: HTMLElement | undefined | null; private systemLogSource: LogStruct[] = []; + private logTreeNodes: LogTreeNode[] = []; + private expansionDiv: HTMLDivElement | undefined | null; + private expansionUpIcon: LitIcon | undefined | null; + private expansionDownIcon: LitIcon | undefined | null; private expandedNodeList: Set = new Set(); private logLevel: string[] = ['Debug', 'Info', 'Warn', 'Error','Fatal']; + private selectTreeDepth: number = 0; set data(systemLogDetailParam: SelectionParam) { this.systemLogSource = []; @@ -45,6 +51,18 @@ export class TabPaneHiLogSummary extends BaseElement { initElements(): void { this.logSummaryTable = this.shadowRoot?.querySelector('#tab-summary'); this.summaryDownLoadTbl = this.shadowRoot?.querySelector('#tb-hilog-summary'); + this.expansionDiv = this.shadowRoot?.querySelector('.expansion-div'); + this.expansionUpIcon = this.shadowRoot?.querySelector('.expansion-up-icon'); + this.expansionDownIcon = this.shadowRoot?.querySelector('.expansion-down-icon'); + let summaryTreeLevel: string[] = ['Level', '/Process', '/Tag', '/Message'] + this.shadowRoot?.querySelectorAll('.head-label').forEach(summaryTreeHead => { + summaryTreeHead.addEventListener('click', ()=>{ + this.selectTreeDepth = summaryTreeLevel.indexOf(summaryTreeHead.textContent!); + this.expandedNodeList.clear(); + this.refreshSelectDepth(this.logTreeNodes); + this.refreshRowNodeTable(true); + }); + }); } initHtml(): string { @@ -64,11 +82,11 @@ export class TabPaneHiLogSummary extends BaseElement { .tree-row-tr:hover { background-color: #DEEDFF; } - td, .head-label { + td, .head-label, .head-count { white-space: nowrap; overflow: hidden; } - .head-label { + .head-label, .head-count { font-weight: bold; } .count-column-td, .head-count { @@ -87,8 +105,17 @@ export class TabPaneHiLogSummary extends BaseElement { }
    - - +
    +
    + + +
    + + + + +
    +