11cb0ef41Sopenharmony_ci// Copyright 2021 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ciimport {Timeline} from '../../timeline.mjs'; 61cb0ef41Sopenharmony_ciimport {SelectTimeEvent} from '../events.mjs'; 71cb0ef41Sopenharmony_ciimport {CSSColor, delay, SVG} from '../helper.mjs'; 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ciimport {TimelineTrackBase} from './timeline-track-base.mjs' 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ciconst kItemHeight = 8; 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ciexport class TimelineTrackStackedBase extends TimelineTrackBase { 141cb0ef41Sopenharmony_ci _originalContentWidth = 0; 151cb0ef41Sopenharmony_ci _drawableItems = new Timeline(); 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ci _updateChunks() { 181cb0ef41Sopenharmony_ci // We don't need to update the chunks here. 191cb0ef41Sopenharmony_ci this._updateDimensions(); 201cb0ef41Sopenharmony_ci this.requestUpdate(); 211cb0ef41Sopenharmony_ci } 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ci set data(timeline) { 241cb0ef41Sopenharmony_ci super.data = timeline; 251cb0ef41Sopenharmony_ci this._contentWidth = 0; 261cb0ef41Sopenharmony_ci if (timeline.values.length > 0) this._prepareDrawableItems(); 271cb0ef41Sopenharmony_ci } 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci _handleDoubleClick(event) { 301cb0ef41Sopenharmony_ci if (event.button !== 0) return; 311cb0ef41Sopenharmony_ci this._selectionHandler.clearSelection(); 321cb0ef41Sopenharmony_ci const item = this._getDrawableItemForEvent(event); 331cb0ef41Sopenharmony_ci if (item === undefined) return; 341cb0ef41Sopenharmony_ci event.stopImmediatePropagation(); 351cb0ef41Sopenharmony_ci this.dispatchEvent(new SelectTimeEvent(item.startTime, item.endTime)); 361cb0ef41Sopenharmony_ci return false; 371cb0ef41Sopenharmony_ci } 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci _getStackDepthForEvent(event) { 401cb0ef41Sopenharmony_ci return Math.floor(event.layerY / kItemHeight) - 1; 411cb0ef41Sopenharmony_ci } 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci _getDrawableItemForEvent(event) { 441cb0ef41Sopenharmony_ci const depth = this._getStackDepthForEvent(event); 451cb0ef41Sopenharmony_ci const time = this.positionToTime(event.pageX); 461cb0ef41Sopenharmony_ci const index = this._drawableItems.find(time); 471cb0ef41Sopenharmony_ci for (let i = index - 1; i > 0; i--) { 481cb0ef41Sopenharmony_ci const item = this._drawableItems.at(i); 491cb0ef41Sopenharmony_ci if (item.depth != depth) continue; 501cb0ef41Sopenharmony_ci if (item.endTime < time) continue; 511cb0ef41Sopenharmony_ci return item; 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci return undefined; 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci _drawableItemToLogEntry(item) { 571cb0ef41Sopenharmony_ci return item; 581cb0ef41Sopenharmony_ci } 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci _getEntryForEvent(event) { 611cb0ef41Sopenharmony_ci const item = this._getDrawableItemForEvent(event); 621cb0ef41Sopenharmony_ci const logEntry = this._drawableItemToLogEntry(item); 631cb0ef41Sopenharmony_ci if (item === undefined) return undefined; 641cb0ef41Sopenharmony_ci const style = this.toolTipTargetNode.style; 651cb0ef41Sopenharmony_ci style.left = `${event.layerX}px`; 661cb0ef41Sopenharmony_ci style.top = `${(item.depth + 1) * kItemHeight}px`; 671cb0ef41Sopenharmony_ci style.height = `${kItemHeight}px` 681cb0ef41Sopenharmony_ci return logEntry; 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci _prepareDrawableItems() { 721cb0ef41Sopenharmony_ci // Subclass responsibility. 731cb0ef41Sopenharmony_ci } 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci _adjustStackDepth(maxDepth) { 761cb0ef41Sopenharmony_ci // Account for empty top line 771cb0ef41Sopenharmony_ci maxDepth++; 781cb0ef41Sopenharmony_ci this._adjustHeight(maxDepth * kItemHeight); 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci _scaleContent(currentWidth) { 821cb0ef41Sopenharmony_ci if (this._originalContentWidth == 0) return; 831cb0ef41Sopenharmony_ci // Instead of repainting just scale the content. 841cb0ef41Sopenharmony_ci const ratio = currentWidth / this._originalContentWidth; 851cb0ef41Sopenharmony_ci this._scalableContentNode.style.transform = `scale(${ratio}, 1)`; 861cb0ef41Sopenharmony_ci this.style.setProperty('--txt-scale', `scale(${1 / ratio}, 1)`); 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci async _drawContent() { 901cb0ef41Sopenharmony_ci if (this._originalContentWidth > 0) return; 911cb0ef41Sopenharmony_ci this._originalContentWidth = parseInt(this.timelineMarkersNode.style.width); 921cb0ef41Sopenharmony_ci this._scalableContentNode.innerHTML = ''; 931cb0ef41Sopenharmony_ci let buffer = ''; 941cb0ef41Sopenharmony_ci const add = async () => { 951cb0ef41Sopenharmony_ci const svg = SVG.svg(); 961cb0ef41Sopenharmony_ci svg.innerHTML = buffer; 971cb0ef41Sopenharmony_ci this._scalableContentNode.appendChild(svg); 981cb0ef41Sopenharmony_ci buffer = ''; 991cb0ef41Sopenharmony_ci await delay(50); 1001cb0ef41Sopenharmony_ci }; 1011cb0ef41Sopenharmony_ci const items = this._drawableItems.values; 1021cb0ef41Sopenharmony_ci for (let i = 0; i < items.length; i++) { 1031cb0ef41Sopenharmony_ci if ((i % 3000) == 0) await add(); 1041cb0ef41Sopenharmony_ci buffer += this._drawItem(items[i], i); 1051cb0ef41Sopenharmony_ci } 1061cb0ef41Sopenharmony_ci add(); 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci _drawItem(item, i, outline = false) { 1101cb0ef41Sopenharmony_ci const x = roundTo3Digits(this.timeToPosition(item.time)); 1111cb0ef41Sopenharmony_ci const y = (item.depth + 1) * kItemHeight; 1121cb0ef41Sopenharmony_ci let width = roundTo3Digits(item.duration * this._timeToPixel); 1131cb0ef41Sopenharmony_ci if (outline) { 1141cb0ef41Sopenharmony_ci return `<rect x=${x} y=${y} width=${width} height=${ 1151cb0ef41Sopenharmony_ci kItemHeight - 1} class=fs />`; 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci let color = this._legend.colorForType(item.type); 1181cb0ef41Sopenharmony_ci if (i % 2 == 1) { 1191cb0ef41Sopenharmony_ci color = CSSColor.darken(color, 20); 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci return `<rect x=${x} y=${y} width=${width} height=${kItemHeight - 1} fill=${ 1221cb0ef41Sopenharmony_ci color} class=f />`; 1231cb0ef41Sopenharmony_ci } 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci _drawItemText(item) { 1261cb0ef41Sopenharmony_ci const type = item.type; 1271cb0ef41Sopenharmony_ci const kHeight = 9; 1281cb0ef41Sopenharmony_ci const x = this.timeToPosition(item.time); 1291cb0ef41Sopenharmony_ci const y = item.depth * (kHeight + 1); 1301cb0ef41Sopenharmony_ci let width = item.duration * this._timeToPixel; 1311cb0ef41Sopenharmony_ci width -= width * 0.1; 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci let buffer = ''; 1341cb0ef41Sopenharmony_ci if (width < 15 || type == 'Other') return buffer; 1351cb0ef41Sopenharmony_ci const rawName = item.entry.getName(); 1361cb0ef41Sopenharmony_ci if (rawName.length == 0) return buffer; 1371cb0ef41Sopenharmony_ci const kChartWidth = 5; 1381cb0ef41Sopenharmony_ci const maxChars = Math.floor(width / kChartWidth) 1391cb0ef41Sopenharmony_ci const text = rawName.substr(0, maxChars); 1401cb0ef41Sopenharmony_ci buffer += `<text x=${x + 1} y=${y - 3} class=txt>${text}</text>` 1411cb0ef41Sopenharmony_ci return buffer; 1421cb0ef41Sopenharmony_ci } 1431cb0ef41Sopenharmony_ci} 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_cifunction roundTo3Digits(value) { 1461cb0ef41Sopenharmony_ci return ((value * 1000) | 0) / 1000; 1471cb0ef41Sopenharmony_ci} 148