1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { BaseElement, element } from '../../base-ui/BaseElement.js'; 17import { SelectionData } from '../bean/BoxSelection.js'; 18import { Utils } from './trace/base/Utils.js'; 19 20@element('stack-bar') 21export class StackBar extends BaseElement { 22 private container: HTMLDivElement | undefined | null; 23 24 static get observedAttributes() { 25 return ['mode']; // max min hidden show 三种状态 26 } 27 28 set data(val: Array<SelectionData>) { 29 let map = new Map<string, StackValue>(); 30 for (let v of val) { 31 if (map.has(v.state)) { 32 let sv = map.get(v.state); 33 sv!.value = sv!.value + v.wallDuration; 34 sv!.state = v.state + ' : ' + sv!.value.toFixed(7) + 'ms'; 35 } else { 36 let sv = new StackValue(); 37 sv.value = v.wallDuration; 38 sv.state = v.state + ' : ' + sv.value.toFixed(7) + 'ms'; 39 sv.color = Utils.getStateColor(v.stateJX); 40 map.set(v.state, sv); 41 } 42 } 43 let totalDuration = 0; 44 let arr: Array<StackValue> = []; 45 for (let key of map.keys()) { 46 if (key == ' ') { 47 totalDuration = map.get(key)!.value; 48 } else { 49 arr.push(map.get(key)!); 50 } 51 } 52 arr.sort((a, b) => a.value - b.value); 53 this.container!.innerHTML = ''; 54 for (let stackValue of arr) { 55 this.container!.appendChild(this.createBarElement(stackValue, totalDuration)); 56 } 57 } 58 59 initElements(): void { 60 this.container = this.shadowRoot?.querySelector('#container'); 61 } 62 63 initHtml(): string { 64 return ` 65 <style> 66 :host([mode='hidden']){ 67 display: none; 68 } 69 :host{ 70 display: block; 71 /*background-color: rebeccapurple;*/ 72 } 73 .state-text{ 74 width: 10%;display: inline-block;overflow: hidden;white-space: nowrap;padding: 5px; margin-right: 2px;font-size: 9pt; 75 } 76 </style> 77 <div style="display: flex;flex-direction: row;" id="container"> 78 </div> 79 `; 80 } 81 82 getStateWidth(state: string): number { 83 let canvas = document.createElement('canvas'); 84 let context = canvas.getContext('2d'); 85 context!.font = '9pt'; 86 let metrics = context!.measureText(state); 87 return metrics.width; 88 } 89 90 createBarElement(sv: StackValue, total: number): HTMLDivElement { 91 let bar = document.createElement('div'); 92 bar.setAttribute('class', 'state-text'); 93 bar.setAttribute('need-width', this.getStateWidth(sv.state) + ''); 94 bar.style.backgroundColor = sv.color; 95 bar.textContent = sv.state; 96 if (sv.state.startsWith('Sleeping')) { 97 bar.style.color = '#555555'; 98 } else { 99 bar.style.color = '#ffffff'; 100 } 101 let weight = ((sv.value * 1.0) / total) * 100.0; 102 if (weight < 1) { 103 weight = 1; 104 } 105 bar.style.width = weight + '%'; 106 bar.addEventListener('mouseover', (event) => { 107 let needWidth = parseFloat(bar.getAttribute('need-width')!); 108 let trueWidth = parseFloat(window.getComputedStyle(bar).width); 109 if (trueWidth < needWidth) { 110 bar.style.width = needWidth + 100 + 'px'; 111 } 112 }); 113 bar.addEventListener('mouseleave', (event) => { 114 let weight = ((sv.value * 1.0) / total) * 100.0; 115 if (weight < 1) { 116 weight = 1; 117 } 118 bar.style.width = weight + '%'; 119 }); 120 return bar; 121 } 122} 123 124export class StackValue { 125 state: string = ''; 126 color: string = ''; 127 value: number = 0; 128} 129