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;width: 100%;" 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.00 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.00 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}