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 { 17 BaseStruct, 18 drawLoadingFrame, 19 isFrameContainPoint, 20 ns2x, 21 Rect, 22 Render, 23 RequestMessage, 24} from './ProcedureWorkerCommon'; 25import { TraceRow } from '../../component/trace/base/TraceRow'; 26 27export class EnergySystemRender extends Render { 28 renderMainThread( 29 req: { 30 useCache: boolean; 31 context: CanvasRenderingContext2D; 32 type: string; 33 }, 34 row: TraceRow<EnergySystemStruct> 35 ): void { 36 let systemList = row.dataList; 37 let systemFilter = row.dataListCache; 38 system( 39 systemList, 40 systemFilter, 41 TraceRow.range!.startNS || 0, 42 TraceRow.range!.endNS || 0, 43 TraceRow.range!.totalNS || 0, 44 row.frame, 45 req.useCache || !TraceRow.range!.refresh 46 ); 47 drawLoadingFrame(req.context, row.dataListCache, row); 48 drawProcedureWorkerEnergy(req, systemFilter, row); 49 } 50} 51 52function drawProcedureWorkerEnergy( 53 req: { 54 useCache: boolean; 55 context: CanvasRenderingContext2D; 56 type: string; 57 }, 58 systemFilter: Array<EnergySystemStruct>, 59 row: TraceRow<EnergySystemStruct> 60): void { 61 req.context.beginPath(); 62 let find = false; 63 let energySystemData: unknown = {}; 64 for (let i = 0; i < systemFilter.length; i++) { 65 let energySysStruct = systemFilter[i]; 66 EnergySystemStruct.draw(req.context, energySysStruct); 67 if (row.isHover && energySysStruct.frame && isFrameContainPoint(energySysStruct.frame, row.hoverX, row.hoverY)) { 68 EnergySystemStruct.hoverEnergySystemStruct = energySysStruct; 69 if (energySysStruct.type === 0) { 70 if (energySysStruct.count !== undefined) { 71 // @ts-ignore 72 energySystemData.workScheduler = energySysStruct.count; 73 } else { 74 // @ts-ignore 75 energySystemData.workScheduler = '0'; 76 } 77 } 78 if (energySysStruct.type === 1) { 79 if (energySysStruct.count !== undefined) { 80 // @ts-ignore 81 energySystemData.power = energySysStruct.count + ''; 82 } else { 83 // @ts-ignore 84 energySystemData.power = '0'; 85 } 86 } 87 if (energySysStruct.type === 2) { 88 if (energySysStruct.count !== undefined) { 89 // @ts-ignore 90 energySystemData.location = energySysStruct.count + ''; 91 } else { 92 // @ts-ignore 93 energySystemData.location = '0'; 94 } 95 } 96 find = true; 97 } 98 } 99 if (!find && row.isHover) { 100 EnergySystemStruct.hoverEnergySystemStruct = undefined; 101 } 102 if (EnergySystemStruct.hoverEnergySystemStruct) { 103 EnergySystemStruct.hoverEnergySystemStruct!.workScheduler = 104 // @ts-ignore 105 energySystemData.workScheduler === undefined ? '0' : energySystemData.workScheduler; 106 EnergySystemStruct.hoverEnergySystemStruct!.power = 107 // @ts-ignore 108 energySystemData.power === undefined ? '0' : energySystemData.power; 109 EnergySystemStruct.hoverEnergySystemStruct!.location = 110 // @ts-ignore 111 energySystemData.location === undefined ? '0' : energySystemData.location; 112 } 113 let spApplication = document.getElementsByTagName('sp-application')[0]; 114 let isDark = spApplication.hasAttribute('dark'); 115 drawLegend(req, isDark); 116 req.context.closePath(); 117} 118 119export function drawLegend( 120 req: { 121 useCache: boolean; 122 context: CanvasRenderingContext2D; 123 type: string; 124 }, 125 isDark?: boolean 126): void { 127 let textList = ['WORKSCHEDULER', 'POWER_RUNNINGLOCK', 'LOCATION']; 128 for (let index = 0; index < textList.length; index++) { 129 let text = req.context.measureText(textList[index]); 130 req.context.fillStyle = EnergySystemStruct.getColor(index); 131 let canvasEndX = req.context.canvas.clientWidth - EnergySystemStruct.OFFSET_WIDTH; 132 let textColor = isDark ? '#FFFFFF' : '#333'; 133 if (textList[index] === 'WORKSCHEDULER') { 134 req.context.fillRect(canvasEndX - EnergySystemStruct.itemNumber * 120, 12, 8, 8); 135 req.context.globalAlpha = 1; 136 req.context.textBaseline = 'middle'; 137 req.context.fillStyle = textColor; 138 req.context.fillText(textList[index], canvasEndX - EnergySystemStruct.itemNumber * 120 + 10, 18); 139 EnergySystemStruct.currentTextWidth = canvasEndX - EnergySystemStruct.itemNumber * 120 + 40 + text.width; 140 } else { 141 req.context.fillRect(EnergySystemStruct.currentTextWidth, 12, 8, 8); 142 req.context.globalAlpha = 1; 143 req.context.fillStyle = textColor; 144 req.context.textBaseline = 'middle'; 145 req.context.fillText(textList[index], EnergySystemStruct.currentTextWidth + 12, 18); 146 EnergySystemStruct.currentTextWidth = EnergySystemStruct.currentTextWidth + 40 + text.width; 147 } 148 } 149 req.context.fillStyle = '#333'; 150} 151 152export function systemData( 153 data: Array<EnergySystemStruct>, 154 startNS: number, 155 endNS: number, 156 totalNS: number, 157 frame: Rect 158): void { 159 for (let index = 0; index < data.length; index++) { 160 let systemItem = data[index]; 161 if (index === data.length - 1) { 162 systemItem.dur = (endNS || 0) - (systemItem.startNs || 0); 163 } else { 164 systemItem.dur = (data[index + 1].startNs! || 0) - (systemItem.startNs! || 0); 165 } 166 if (systemItem.count === 0) { 167 systemItem.dur = 0; 168 } 169 if ( 170 (systemItem.startNs || 0) + (systemItem.dur || 0) > (startNS || 0) && 171 (systemItem.startNs || 0) < (endNS || 0) 172 ) { 173 EnergySystemStruct.setSystemFrame(systemItem, 10, startNS || 0, endNS || 0, totalNS || 0, frame); 174 } 175 } 176} 177 178export function system( 179 systemList: Array<EnergySystemStruct>, 180 res: Array<EnergySystemStruct>, 181 startNS: number, 182 endNS: number, 183 totalNS: number, 184 frame: Rect, 185 use: boolean 186): void { 187 if (use && res.length > 0) { 188 let lockData: EnergySystemStruct[] = []; 189 let locationData: EnergySystemStruct[] = []; 190 let workData: EnergySystemStruct[] = []; 191 res.forEach((item) => { 192 if (item.dataType === 1) { 193 lockData.push(item); 194 } else if (item.dataType === 2) { 195 locationData.push(item); 196 } else { 197 workData.push(item); 198 } 199 }); 200 if (lockData.length > 0) { 201 systemData(lockData, startNS, endNS, totalNS, frame); 202 } 203 if (locationData.length > 0) { 204 systemData(locationData, startNS, endNS, totalNS, frame); 205 } 206 if (workData.length > 0) { 207 systemData(workData, startNS, endNS, totalNS, frame); 208 } 209 return; 210 } 211 res.length = 0; 212 setEnergySystemFilter(systemList, res, startNS, endNS, totalNS, frame); 213} 214function setEnergySystemFilter( 215 systemList: Array<unknown>, 216 res: Array<unknown>, 217 startNS: number, 218 endNS: number, 219 totalNS: number, 220 frame: Rect 221): void { 222 if (systemList) { 223 for (let i = 0; i < 3; i++) { 224 let arr = systemList[i]; 225 if (arr) { 226 //@ts-ignore 227 for (let index = 0; index < arr.length; index++) { 228 //@ts-ignore 229 let item = arr[index]; 230 //@ts-ignore 231 if (index === arr.length - 1) { 232 item.dur = endNS - (item.startNs || 0); 233 } else { 234 //@ts-ignore 235 item.dur = (arr[index + 1].startNs || 0) - (item.startNs || 0); 236 } 237 if (item.count === 0) { 238 item.dur = 0; 239 } 240 if ((item.startNs || 0) + (item.dur || 0) > startNS && (item.startNs || 0) < endNS) { 241 EnergySystemStruct.setSystemFrame(item, 10, startNS, endNS, totalNS, frame); 242 res.push(item); 243 } 244 } 245 } 246 } 247 } 248} 249 250export class EnergySystemStruct extends BaseStruct { 251 static hoverEnergySystemStruct: EnergySystemStruct | undefined; 252 static selectEnergySystemStruct: EnergySystemStruct | undefined; 253 static itemNumber: number = 3; 254 static currentTextWidth: number = 0; 255 static OFFSET_WIDTH: number = 266; 256 type: number | undefined; 257 startNs: number | undefined; 258 dur: number | undefined; 259 count: number | undefined; 260 token: number | undefined; 261 workScheduler: string | undefined; 262 power: string | undefined; 263 location: string | undefined; 264 id: number | undefined; 265 eventName: string | undefined; 266 eventValue: string | undefined; 267 appKey: string | undefined; 268 dataType: number | undefined; 269 270 static draw(energySystemContext: CanvasRenderingContext2D, data: EnergySystemStruct): void { 271 if (data.frame) { 272 let width = data.frame.width || 0; 273 energySystemContext.globalAlpha = 1.0; 274 energySystemContext.lineWidth = 1; 275 energySystemContext.fillStyle = this.getColor(data.type!); 276 energySystemContext.strokeStyle = this.getColor(data.type!); 277 energySystemContext.fillRect(data.frame.x, data.frame.y + 4, width, data.frame.height); 278 } 279 energySystemContext.globalAlpha = 1.0; 280 energySystemContext.lineWidth = 1; 281 } 282 283 static setSystemFrame( 284 systemNode: EnergySystemStruct, 285 padding: number, 286 startNS: number, 287 endNS: number, 288 totalNS: number, 289 frame: Rect 290 ): void { 291 let systemStartPointX: number; 292 let systemEndPointX: number; 293 if ((systemNode.startNs || 0) < startNS) { 294 systemStartPointX = 0; 295 } else { 296 systemStartPointX = ns2x(systemNode.startNs || 0, startNS, endNS, totalNS, frame); 297 } 298 if ((systemNode.startNs || 0) + (systemNode.dur || 0) > endNS) { 299 systemEndPointX = frame.width; 300 } else { 301 systemEndPointX = ns2x((systemNode.startNs || 0) + (systemNode.dur || 0), startNS, endNS, totalNS, frame); 302 } 303 let frameWidth: number = systemEndPointX - systemStartPointX <= 1 ? 1 : systemEndPointX - systemStartPointX; 304 if (!systemNode.frame) { 305 systemNode.frame = new Rect(0, 0, 0, 0); 306 } 307 systemNode.frame.x = Math.floor(systemStartPointX); 308 if (systemNode.type === 0) { 309 systemNode.frame.y = frame.y + padding * 2.5; 310 } else if (systemNode.type === 1) { 311 systemNode.frame.y = frame.y + padding * 4.5; 312 } else if (systemNode.type === 2) { 313 systemNode.frame.y = frame.y + padding * 6.5; 314 } 315 systemNode.frame.width = Math.ceil(frameWidth); 316 systemNode.frame.height = Math.floor(padding); 317 } 318 319 static getColor(textItem: number): string { 320 switch (textItem) { 321 case 0: 322 return '#E64566'; 323 case 1: 324 return '#FFC880'; 325 default: 326 return '#564AF7'; 327 } 328 } 329} 330