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