UNPKG

@yuebai008/cli

Version:

Command line interface for rapid qg-minigame development

1 lines 36.8 kB
import*as Common from"../../../../core/common/common.js";import*as i18n from"../../../../core/i18n/i18n.js";import*as Platform from"../../../../core/platform/platform.js";import*as TraceEngine from"../../../../models/trace/trace.js";import*as UI from"../../legacy.js";import*as ThemeSupport from"../../theme_support/theme_support.js";import{ChartViewport}from"./ChartViewport.js";import flameChartStyles from"./flameChart.css.legacy.js";import{DEFAULT_FONT_SIZE,getFontFamilyForCanvas}from"./Font.js";import{TimelineGrid}from"./TimelineGrid.js";const UIStrings={flameChart:"Flame Chart",sHovered:"{PH1} hovered",sSelected:"{PH1} selected",sExpanded:"{PH1} expanded",sCollapsed:"{PH1} collapsed"},str_=i18n.i18n.registerUIStrings("ui/legacy/components/perf_ui/FlameChart.ts",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_);export class FlameChartDelegate{windowChanged(e,t,i){}updateRangeSelection(e,t){}updateSelectedGroup(e,t){}}export class FlameChart extends(Common.ObjectWrapper.eventMixin(UI.Widget.VBox)){groupExpansionSetting;groupExpansionState;flameChartDelegate;chartViewport;dataProvider;candyStripePattern;viewportElement;canvas;entryInfo;markerHighlighElement;highlightElement;selectedElement;rulerEnabled;barHeight;textBaseline;textPadding;headerLeftPadding;arrowSide;expansionArrowIndent;headerLabelXPadding;headerLabelYPadding;highlightedMarkerIndex;highlightedEntryIndex;selectedEntryIndex;rawTimelineDataLength;markerPositions;lastMouseOffsetX;selectedGroup;keyboardFocusedGroup;offsetWidth;offsetHeight;dragStartX;dragStartY;lastMouseOffsetY;minimumBoundaryInternal;maxDragOffset;timelineLevels;visibleLevelOffsets;visibleLevels;groupOffsets;rawTimelineData;forceDecorationCache;entryColorsCache;visibleLevelHeights;totalTime;#e;constructor(e,t,i){super(!0),this.#e=`${DEFAULT_FONT_SIZE} ${getFontFamilyForCanvas()}`,this.registerRequiredCSS(flameChartStyles),this.contentElement.classList.add("flame-chart-main-pane"),this.groupExpansionSetting=i,this.groupExpansionState=i&&i.get()||{},this.flameChartDelegate=t,this.chartViewport=new ChartViewport(this),this.chartViewport.show(this.contentElement),this.dataProvider=e,this.viewportElement=this.chartViewport.viewportElement,this.canvas=this.viewportElement.createChild("canvas","fill"),this.candyStripePattern=null,this.canvas.tabIndex=0,UI.ARIAUtils.setLabel(this.canvas,i18nString(UIStrings.flameChart)),UI.ARIAUtils.markAsTree(this.canvas),this.setDefaultFocusedElement(this.canvas),this.canvas.classList.add("flame-chart-canvas"),this.canvas.addEventListener("mousemove",this.onMouseMove.bind(this),!1),this.canvas.addEventListener("mouseout",this.onMouseOut.bind(this),!1),this.canvas.addEventListener("click",this.onClick.bind(this),!1),this.canvas.addEventListener("keydown",this.onKeyDown.bind(this),!1),this.canvas.addEventListener("contextmenu",this.#t.bind(this),!1),this.entryInfo=this.viewportElement.createChild("div","flame-chart-entry-info"),this.markerHighlighElement=this.viewportElement.createChild("div","flame-chart-marker-highlight-element"),this.highlightElement=this.viewportElement.createChild("div","flame-chart-highlight-element"),this.selectedElement=this.viewportElement.createChild("div","flame-chart-selected-element"),this.canvas.addEventListener("focus",(()=>{this.dispatchEventToListeners(Events.CanvasFocused)}),!1),UI.UIUtils.installDragHandle(this.viewportElement,this.startDragging.bind(this),this.dragging.bind(this),this.endDragging.bind(this),null),this.rulerEnabled=!0,this.barHeight=17,this.textBaseline=5,this.textPadding=5,this.chartViewport.setWindowTimes(e.minimumBoundary(),e.minimumBoundary()+e.totalTime()),this.headerLeftPadding=6,this.arrowSide=8,this.expansionArrowIndent=this.headerLeftPadding+this.arrowSide/2,this.headerLabelXPadding=3,this.headerLabelYPadding=2,this.highlightedMarkerIndex=-1,this.highlightedEntryIndex=-1,this.selectedEntryIndex=-1,this.rawTimelineDataLength=0,this.markerPositions=new Map,this.lastMouseOffsetX=0,this.selectedGroup=-1,this.keyboardFocusedGroup=-1,ThemeSupport.ThemeSupport.instance().addEventListener(ThemeSupport.ThemeChangeEvent.eventName,(()=>{this.scheduleUpdate()}))}willHide(){this.hideHighlight()}setBarHeight(e){this.barHeight=e}setTextBaseline(e){this.textBaseline=e}setTextPadding(e){this.textPadding=e}enableRuler(e){this.rulerEnabled=e}alwaysShowVerticalScroll(){this.chartViewport.alwaysShowVerticalScroll()}disableRangeSelection(){this.chartViewport.disableRangeSelection()}highlightEntry(e){this.highlightedEntryIndex!==e&&this.dataProvider.entryColor(e)&&(this.highlightedEntryIndex=e,this.updateElementPosition(this.highlightElement,this.highlightedEntryIndex),this.dispatchEventToListeners(Events.EntryHighlighted,e))}hideHighlight(){this.entryInfo.removeChildren(),this.highlightedEntryIndex=-1,this.updateElementPosition(this.highlightElement,this.highlightedEntryIndex),this.dispatchEventToListeners(Events.EntryHighlighted,-1)}createCandyStripePattern(){const e=17,t=document.createElement("canvas");t.width=e,t.height=e;const i=t.getContext("2d");i.translate(8.5,8.5),i.rotate(.25*Math.PI),i.translate(-8.5,-8.5),i.fillStyle="rgba(255, 0, 0, 0.8)";for(let e=-17;e<34;e+=3)i.fillRect(e,-17,1,51);return i.createPattern(t,"repeat")}resetCanvas(){const e=window.devicePixelRatio,t=Math.round(this.offsetWidth*e),i=Math.round(this.offsetHeight*e);this.canvas.width=t,this.canvas.height=i,this.canvas.style.width=t/e+"px",this.canvas.style.height=i/e+"px"}windowChanged(e,t,i){this.flameChartDelegate.windowChanged(e,t,i)}updateRangeSelection(e,t){this.flameChartDelegate.updateRangeSelection(e,t)}setSize(e,t){this.offsetWidth=e,this.offsetHeight=t}startDragging(e){return this.hideHighlight(),this.maxDragOffset=0,this.dragStartX=e.pageX,this.dragStartY=e.pageY,!0}dragging(e){const t=e.pageX-this.dragStartX,i=e.pageY-this.dragStartY;this.maxDragOffset=Math.max(this.maxDragOffset,Math.sqrt(t*t+i*i))}endDragging(e){this.updateHighlight()}timelineData(){if(!this.dataProvider)return null;const e=this.dataProvider.timelineData();return(e!==this.rawTimelineData||e&&e.entryStartTimes.length!==this.rawTimelineDataLength)&&this.processTimelineData(e),this.rawTimelineData||null}revealEntry(e){const t=this.timelineData();if(!t)return;const i=this.chartViewport.windowLeftTime(),s=this.chartViewport.windowRightTime(),r=t.entryStartTimes[e],n=t.entryTotalTimes[e],o=r+n;let a=Math.min(n,s-i);const l=t.entryLevels[e];this.chartViewport.setScrollOffset(this.levelToOffset(l),this.levelHeight(l));const h=(s-i)/this.offsetWidth;if(a=Math.max(a,30*h),i>o){const e=i-o+a;this.windowChanged(i-e,s-e,!0)}else if(s<r){const e=r-s+a;this.windowChanged(i+e,s+e,!0)}}setWindowTimes(e,t,i){this.chartViewport.setWindowTimes(e,t,i),this.updateHighlight()}onMouseMove(e){const t=e;if(this.lastMouseOffsetX=t.offsetX,this.lastMouseOffsetY=t.offsetY,this.enabled()&&!this.chartViewport.isDragging())return this.coordinatesToGroupIndex(t.offsetX,t.offsetY,!0)>=0?(this.hideHighlight(),void(this.viewportElement.style.cursor="pointer")):void this.updateHighlight()}updateHighlight(){const e=this.coordinatesToEntryIndex(this.lastMouseOffsetX,this.lastMouseOffsetY);if(-1!==e)this.chartViewport.isDragging()||(this.updatePopover(e),this.viewportElement.style.cursor=this.dataProvider.canJumpToEntry(e)?"pointer":"default",this.highlightEntry(e));else{this.hideHighlight();const e=this.coordinatesToGroupIndex(this.lastMouseOffsetX,this.lastMouseOffsetY,!1);e>=0&&this.rawTimelineData&&this.rawTimelineData.groups&&this.rawTimelineData.groups[e].selectable?this.viewportElement.style.cursor="pointer":this.viewportElement.style.cursor="default"}}onMouseOut(){this.lastMouseOffsetX=-1,this.lastMouseOffsetY=-1,this.hideHighlight()}updatePopover(e){if(e===this.highlightedEntryIndex)return void this.updatePopoverOffset();this.entryInfo.removeChildren();const t=this.dataProvider.prepareHighlightedEntryInfo(e);t&&(this.entryInfo.appendChild(t),this.updatePopoverOffset())}updatePopoverOffset(){const e=this.lastMouseOffsetX,t=this.lastMouseOffsetY,i=this.entryInfo.parentElement?this.entryInfo.parentElement.clientWidth:0,s=this.entryInfo.parentElement?this.entryInfo.parentElement.clientHeight:0,r=this.entryInfo.clientWidth,n=this.entryInfo.clientHeight;let o,a;for(let l=0;l<4;++l){const h=2&l?-10-r:10,d=1&l?-6-n:6;if(o=Platform.NumberUtilities.clamp(e+h,0,i-r),a=Platform.NumberUtilities.clamp(t+d,0,s-n),o>=e||e>=o+r||a>=t||t>=a+n)break}this.entryInfo.style.left=o+"px",this.entryInfo.style.top=a+"px"}onClick(e){const t=e;this.focus();if(this.maxDragOffset>5)return;this.selectGroup(this.coordinatesToGroupIndex(t.offsetX,t.offsetY,!1)),this.toggleGroupExpand(this.coordinatesToGroupIndex(t.offsetX,t.offsetY,!0));const i=this.timelineData();if(t.shiftKey&&-1!==this.highlightedEntryIndex&&i){const e=i.entryStartTimes[this.highlightedEntryIndex],t=e+i.entryTotalTimes[this.highlightedEntryIndex];this.chartViewport.setRangeSelection(e,t)}else this.chartViewport.onClick(t),this.dispatchEventToListeners(Events.EntryInvoked,this.highlightedEntryIndex)}selectGroup(e){if(e<0||this.selectedGroup===e)return;if(!this.rawTimelineData)return;const t=this.rawTimelineData.groups;if(!t)return;this.keyboardFocusedGroup=e,this.scrollGroupIntoView(e);const i=t[e].name;t[e].selectable?(this.selectedGroup=e,this.flameChartDelegate.updateSelectedGroup(this,t[e]),this.resetCanvas(),this.draw(),UI.ARIAUtils.alert(i18nString(UIStrings.sSelected,{PH1:i}))):(this.deselectAllGroups(),UI.ARIAUtils.alert(i18nString(UIStrings.sHovered,{PH1:i})))}deselectAllGroups(){this.selectedGroup=-1,this.flameChartDelegate.updateSelectedGroup(this,null),this.resetCanvas(),this.draw()}deselectAllEntries(){this.selectedEntryIndex=-1,this.resetCanvas(),this.draw()}isGroupFocused(e){return e===this.selectedGroup||e===this.keyboardFocusedGroup}scrollGroupIntoView(e){if(e<0)return;if(!this.rawTimelineData)return;const t=this.rawTimelineData.groups,i=this.groupOffsets;if(!i||!t)return;const s=i[e];let r=i[e+1];e===t.length-1&&(r+=t[e].style.padding);const n=0===e?0:s,o=Math.min(r-n,this.chartViewport.chartHeight());this.chartViewport.setScrollOffset(n,o)}toggleGroupExpand(e){e<0||!this.isGroupCollapsible(e)||this.rawTimelineData&&this.rawTimelineData.groups&&this.expandGroup(e,!this.rawTimelineData.groups[e].expanded)}expandGroup(e,t=!0,i=!1){if(e<0||!this.isGroupCollapsible(e))return;if(!this.rawTimelineData)return;const s=this.rawTimelineData.groups;if(!s)return;const r=s[e];if(r.expanded=t,this.groupExpansionState[r.name]=r.expanded,this.groupExpansionSetting&&this.groupExpansionSetting.set(this.groupExpansionState),this.updateLevelPositions(),this.updateHighlight(),!r.expanded){const t=this.timelineData();if(t){const i=t.entryLevels[this.selectedEntryIndex];this.selectedEntryIndex>=0&&i>=r.startLevel&&(e>=s.length-1||s[e+1].startLevel>i)&&(this.selectedEntryIndex=-1)}}if(this.updateHeight(),this.resetCanvas(),this.draw(),this.scrollGroupIntoView(e),!i){const t=s[e].name,i=r.expanded?i18nString(UIStrings.sExpanded,{PH1:t}):i18nString(UIStrings.sCollapsed,{PH1:t});UI.ARIAUtils.alert(i)}}#t(e){if(-1===this.highlightedEntryIndex)return;const t=this.timelineData();if(!t)return;const i=t.groups.at(this.selectedGroup);i&&i.expanded&&i.showStackContextMenu}onKeyDown(e){if(!UI.KeyboardShortcut.KeyboardShortcut.hasNoModifiers(e)||!this.timelineData())return;!this.handleSelectionNavigation(e)&&this.rawTimelineData&&this.rawTimelineData.groups&&this.handleKeyboardGroupNavigation(e)}bindCanvasEvent(e,t){this.canvas.addEventListener(e,t)}handleKeyboardGroupNavigation(e){const t=e;let i=!1,s=!1;"ArrowUp"===t.code?i=this.selectPreviousGroup():"ArrowDown"===t.code?i=this.selectNextGroup():"ArrowLeft"===t.code?this.keyboardFocusedGroup>=0&&(this.expandGroup(this.keyboardFocusedGroup,!1),i=!0):"ArrowRight"===t.code?this.keyboardFocusedGroup>=0&&(this.expandGroup(this.keyboardFocusedGroup,!0),this.selectFirstChild(),i=!0):"Enter"===t.key&&(s=this.selectFirstEntryInCurrentGroup(),i=s),i&&!s&&this.deselectAllEntries(),i&&t.consume(!0)}selectFirstEntryInCurrentGroup(){if(!this.rawTimelineData)return!1;const e=this.rawTimelineData.groups;if(this.keyboardFocusedGroup<0||!e)return!1;const t=e[this.keyboardFocusedGroup].startLevel;if(t<0)return!1;if(this.keyboardFocusedGroup<e.length-1&&e[this.keyboardFocusedGroup+1].startLevel===t)return!1;if(!this.timelineLevels)return!1;const i=this.timelineLevels[t][0];return this.expandGroup(this.keyboardFocusedGroup,!0),this.setSelectedEntry(i),!0}selectPreviousGroup(){if(this.keyboardFocusedGroup<=0)return!1;const e=this.getGroupIndexToSelect(-1);return this.selectGroup(e),!0}selectNextGroup(){if(!this.rawTimelineData||!this.rawTimelineData.groups)return!1;if(this.keyboardFocusedGroup>=this.rawTimelineData.groups.length-1)return!1;const e=this.getGroupIndexToSelect(1);return this.selectGroup(e),!0}getGroupIndexToSelect(e){if(!this.rawTimelineData||!this.rawTimelineData.groups)throw new Error("No raw timeline data");const t=this.rawTimelineData.groups;let i,s,r=this.keyboardFocusedGroup;do{r+=e,i=this.rawTimelineData.groups[r].name,s=-1!==this.keyboardFocusedGroup&&t[r].style.nestingLevel>t[this.keyboardFocusedGroup].style.nestingLevel}while(r>0&&r<t.length-1&&(!i||s));return r}selectFirstChild(){if(!this.rawTimelineData||!this.rawTimelineData.groups)return;const e=this.rawTimelineData.groups;if(this.keyboardFocusedGroup<0||this.keyboardFocusedGroup>=e.length-1)return;const t=this.keyboardFocusedGroup+1;e[t].style.nestingLevel>e[this.keyboardFocusedGroup].style.nestingLevel&&this.selectGroup(t)}handleSelectionNavigation(e){if(-1===this.selectedEntryIndex)return!1;const t=this.timelineData();if(!t)return!1;function i(e,i){if(!t)throw new Error("No timeline data");const s=t.entryStartTimes[e],r=t.entryStartTimes[i],n=s+t.entryTotalTimes[e];return s<r+t.entryTotalTimes[i]&&r<n}const s=e,r=UI.KeyboardShortcut.Keys;if(s.keyCode===r.Left.code||s.keyCode===r.Right.code){const i=t.entryLevels[this.selectedEntryIndex],n=this.timelineLevels?this.timelineLevels[i]:[];let o=Platform.ArrayUtilities.lowerBound(n,this.selectedEntryIndex,((e,t)=>e-t));return o+=s.keyCode===r.Left.code?-1:1,e.consume(!0),o>=0&&o<n.length&&this.dispatchEventToListeners(Events.EntrySelected,n[o]),!0}if(s.keyCode===r.Up.code||s.keyCode===r.Down.code){let e=t.entryLevels[this.selectedEntryIndex];if(e+=s.keyCode===r.Up.code?-1:1,e<0||this.timelineLevels&&e>=this.timelineLevels.length)return this.deselectAllEntries(),s.consume(!0),!0;const n=t.entryStartTimes[this.selectedEntryIndex]+t.entryTotalTimes[this.selectedEntryIndex]/2,o=this.timelineLevels?this.timelineLevels[e]:[];let a=Platform.ArrayUtilities.upperBound(o,n,(function(e,i){if(!t)throw new Error("No timeline data");return e-t.entryStartTimes[i]}))-1;return!i(this.selectedEntryIndex,o[a])&&(++a,a>=o.length||!i(this.selectedEntryIndex,o[a]))?"ArrowDown"!==s.code&&(this.deselectAllEntries(),s.consume(!0),!0):(s.consume(!0),this.dispatchEventToListeners(Events.EntrySelected,o[a]),!0)}return"Enter"===e.key&&(e.consume(!0),this.dispatchEventToListeners(Events.EntryInvoked,this.selectedEntryIndex),!0)}coordinatesToEntryIndex(e,t){if(e<0||t<0)return-1;const i=this.timelineData();if(!i)return-1;if(t+=this.chartViewport.scrollOffset(),!this.visibleLevelOffsets)throw new Error("No visible level offsets");const s=Platform.ArrayUtilities.upperBound(this.visibleLevelOffsets,t,Platform.ArrayUtilities.DEFAULT_COMPARATOR)-1;if(s<0||this.visibleLevels&&!this.visibleLevels[s])return-1;if(t-this.visibleLevelOffsets[s]>this.levelHeight(s))return-1;for(const[t,r]of this.markerPositions)if(i.entryLevels[t]===s&&r.x<=e&&e<r.x+r.width)return t;const r=i.entryStartTimes,n=this.timelineLevels?this.timelineLevels[s]:[];if(!n||!n.length)return-1;const o=this.chartViewport.pixelToTime(e),a=Math.max(Platform.ArrayUtilities.upperBound(n,o,((e,t)=>e-r[t]))-1,0);function l(t){if(void 0===t)return!1;if(!i)return!1;const s=r[t],n=i.entryTotalTimes[t],o=this.chartViewport.timeToPosition(s),a=this.chartViewport.timeToPosition(s+n);return o-3<e&&e<a+3}let h=n[a];return l.call(this,h)?h:(h=n[a+1],l.call(this,h)?h:-1)}coordinatesToGroupIndex(e,t,i){if(!this.rawTimelineData||!this.rawTimelineData.groups||!this.groupOffsets)return-1;if(e<0||t<0)return-1;t+=this.chartViewport.scrollOffset();const s=this.rawTimelineData.groups||[],r=Platform.ArrayUtilities.upperBound(this.groupOffsets,t,Platform.ArrayUtilities.DEFAULT_COMPARATOR)-1;if(r<0||r>=s.length)return-1;const n=i?s[r].style.height:this.groupOffsets[r+1]-this.groupOffsets[r];if(t-this.groupOffsets[r]>=n)return-1;if(!i)return r;const o=this.canvas.getContext("2d");o.save(),o.font=this.#e;const a=this.headerLeftPadding+this.labelWidthForGroup(o,s[r]);return o.restore(),e>a?-1:r}markerIndexBeforeTime(e){const t=this.timelineData();if(!t)throw new Error("No timeline data");if(!t.markers)throw new Error("No timeline markers");return Platform.ArrayUtilities.lowerBound(t.markers,e,((e,t)=>e-t.startTime()))}draw(){const e=this.timelineData();if(!e)return;const t=this.offsetWidth,i=this.offsetHeight,s=this.canvas.getContext("2d");s.save();const r=window.devicePixelRatio,n=this.chartViewport.scrollOffset();s.scale(r,r),s.fillStyle="rgba(0, 0, 0, 0)",s.fillRect(0,0,t,i),s.translate(0,-n),s.font=this.#e;const{markerIndices:o,colorBuckets:a,titleIndices:l}=this.getDrawableData(s,e);s.save(),this.forEachGroupInViewport(((e,i,r,n,o)=>{this.isGroupFocused(i)&&(s.fillStyle=ThemeSupport.ThemeSupport.instance().getComputedValue("--selected-group-background",this.contentElement),s.fillRect(0,e,t,o-r.style.padding))})),s.restore();for(const[t,{indexes:i}]of a)this.#i(s,e,t,i);const h=Array.from(a.values()).map((e=>e.indexes)).flat();this.#s(s,e,h),this.drawMarkers(s,e,o),this.drawEventTitles(s,e,l,t),s.restore(),this.drawGroupHeaders(t,i),this.drawFlowEvents(s,t,i),this.drawMarkerLines();const d=TimelineGrid.calculateGridOffsets(this),c=this.dataProvider.mainFrameNavigationStartEvents?.()||[];let p=0;const u=e=>{if(0===c.length)return this.formatValue(e,d.precision);if(c.length>p+1){const t=c[p+1];e>TraceEngine.Helpers.Timing.microSecondsToMilliseconds(t.ts)&&p++}const t=c[p];if(t){e-=TraceEngine.Helpers.Timing.microSecondsToMilliseconds(t.ts)-this.zeroTime()}return this.formatValue(e,d.precision)};TimelineGrid.drawCanvasGrid(s,d),this.rulerEnabled&&TimelineGrid.drawCanvasHeaders(s,d,u,3,HeaderHeight),this.updateElementPosition(this.highlightElement,this.highlightedEntryIndex),this.updateElementPosition(this.selectedElement,this.selectedEntryIndex),this.updateMarkerHighlight()}#i(e,t,i,s){e.save(),e.beginPath();for(let i=0;i<s.length;++i){const r=s[i];this.#r(e,t,r)}e.fillStyle=i,e.fill(),e.restore()}#s(e,t,i){const{entryTotalTimes:s,entryStartTimes:r,entryLevels:n}=t;e.save();for(let o=0;o<i.length;++o){const a=i[o],l=t.entryDecorations.at(a);if(!l||l.length<1)continue;l.length>1&&sortDecorationsForRenderingOrder(l);const h=r[a];for(const i of l){const r=s[a];if("CANDY"===i.type){const s=TraceEngine.Helpers.Timing.microSecondsToMilliseconds(i.startAtTime);if(r<s)continue;this.candyStripePattern||(this.candyStripePattern=this.createCandyStripePattern()),e.save(),e.beginPath();const n=this.timeToPositionClipped(h+s),o=this.timeToPositionClipped(h+r);this.#r(e,t,a,{startX:n,width:o-n}),e.fillStyle=this.candyStripePattern,e.fill(),e.restore()}else if("WARNING_TRIANGLE"===i.type){const i=this.timeToPositionClipped(h),s=n[a],r=this.#n(t,a),o=this.levelToOffset(s),l=this.#o(t,a),d=8;e.save(),e.beginPath(),e.rect(i,o,l,r),e.clip(),e.beginPath(),e.fillStyle="red",e.moveTo(i+l-d,o),e.lineTo(i+l,o),e.lineTo(i+l,o+d),e.fill(),e.restore()}}}e.restore()}#r(e,t,i,s){const{entryTotalTimes:r,entryStartTimes:n,entryLevels:o}=t,a=r[i];if(isNaN(a))return;const l=n[i],h=s?.startX||this.timeToPositionClipped(l),d=o[i],c=this.#n(t,i),p=this.levelToOffset(d),u=s?.width||this.#o(t,i);e.rect(h,p,u-.5,c-1)}#n(e,t){const{entryLevels:i}=e,s=i[t];return this.levelHeight(s)}#o(e,t){const{entryTotalTimes:i,entryStartTimes:s}=e,r=i[t],n=s[t],o=this.timeToPositionClipped(n),a=this.timeToPositionClipped(n+r);return Math.max(a-o,1)}getDrawableData(e,t){const i=[],s=[],{entryTotalTimes:r,entryStartTimes:n}=t,o=this.offsetHeight,a=this.chartViewport.scrollOffset(),l=this.visibleLevelOffsets?this.visibleLevelOffsets:new Uint32Array,h=2*this.textPadding+UI.UIUtils.measureTextWidth(e,"…"),d=this.chartViewport.pixelToTimeOffset(h),c=Math.max(Platform.ArrayUtilities.upperBound(l,a,Platform.ArrayUtilities.DEFAULT_COMPARATOR)-1,0),p=new Map;for(let e=c;e<this.dataProvider.maxStackDepth()&&!(this.levelToOffset(e)>a+o);++e){if(!this.visibleLevels||!this.visibleLevels[e])continue;if(!this.timelineLevels)continue;const t=this.timelineLevels[e];let o=1/0;for(let e=Platform.ArrayUtilities.lowerBound(t,this.chartViewport.windowRightTime(),((e,t)=>e-n[t]))-1;e>=0;--e){const a=t[e],l=r[a];if(isNaN(l)){s.push(a);continue}(l>=d||this.forceDecorationCache&&this.forceDecorationCache[a])&&i.push(a);const h=n[a];if(h+l<=this.chartViewport.windowLeftTime())break;const c=this.timeToPositionClipped(h);if(!(c>=o)&&(o=c,this.entryColorsCache)){const e=this.entryColorsCache[a];let t=p.get(e);t||(t={indexes:[]},p.set(e,t)),t.indexes.push(a)}}}return{colorBuckets:p,titleIndices:i,markerIndices:s}}drawGroupHeaders(e,t){const i=this.canvas.getContext("2d"),s=this.chartViewport.scrollOffset(),r=window.devicePixelRatio;if(!this.rawTimelineData)return;const n=this.rawTimelineData.groups||[];if(!n.length)return;const o=this.groupOffsets;if(null==o)return;const a=o[o.length-1];function l(t){i.moveTo(0,t),i.lineTo(e,t)}function h(e,t,s){const r=this.arrowSide*Math.sqrt(3)/2,n=Math.round(r/2);i.save(),i.translate(e,t),i.rotate(s?Math.PI/2:0),i.moveTo(-n,-this.arrowSide/2),i.lineTo(-n,this.arrowSide/2),i.lineTo(r-n,0),i.restore()}i.save(),i.scale(r,r),i.translate(0,-s),i.font=this.#e,i.fillStyle=ThemeSupport.ThemeSupport.instance().getComputedValue("--color-background"),this.forEachGroupInViewport(((t,s,r)=>{const n=r.style.padding;n<5||i.fillRect(0,t-n+2,e,n-4)})),n.length&&a<s+t&&i.fillRect(0,a+2,e,s+t-a),i.strokeStyle=ThemeSupport.ThemeSupport.instance().getComputedValue("--color-background-elevation-1"),i.beginPath(),this.forEachGroupInViewport(((e,t,i,s)=>{s||i.style.padding<4||l(e-2.5)})),l(a+1.5),i.stroke(),this.forEachGroupInViewport(((t,s,r)=>{if(r.style.useFirstLineForOverview)return;if(!this.isGroupCollapsible(s)||r.expanded)return void(!r.style.shareHeaderLine&&this.isGroupFocused(s)&&(i.fillStyle=r.style.backgroundColor,i.fillRect(0,t,e,r.style.height)));let o=s+1;for(;o<n.length&&n[o].style.nestingLevel>r.style.nestingLevel;)o++;const a=o<n.length?n[o].startLevel:this.dataProvider.maxStackDepth();this.drawCollapsedOverviewForGroup(r,t,a)})),i.save(),this.forEachGroupInViewport(((e,t,s)=>{if(i.font=this.#e,this.isGroupCollapsible(t)&&!s.expanded||s.style.shareHeaderLine){const r=this.labelWidthForGroup(i,s)+2;if(this.isGroupFocused(t))i.fillStyle=ThemeSupport.ThemeSupport.instance().getComputedValue("--selected-group-background",this.contentElement);else{const e=Common.Color.parse(s.style.backgroundColor);e&&(i.fillStyle=e.setAlpha(.8).asString())}i.fillRect(this.headerLeftPadding-this.headerLabelXPadding,e+this.headerLabelYPadding,r,s.style.height-2*this.headerLabelYPadding)}i.fillStyle=s.style.color,i.fillText(s.name,Math.floor(this.expansionArrowIndent*(s.style.nestingLevel+1)+this.arrowSide),e+s.style.height-this.textBaseline)})),i.restore(),i.fillStyle=ThemeSupport.ThemeSupport.instance().getComputedValue("--color-text-secondary"),i.beginPath(),this.forEachGroupInViewport(((e,t,i)=>{this.isGroupCollapsible(t)&&h.call(this,this.expansionArrowIndent*(i.style.nestingLevel+1),e+i.style.height-this.textBaseline-this.arrowSide/2,Boolean(i.expanded))})),i.fill(),i.strokeStyle=ThemeSupport.ThemeSupport.instance().getComputedValue("--color-details-hairline-light"),i.beginPath(),i.stroke(),this.forEachGroupInViewport(((e,t,s,r,n)=>{if(this.isGroupFocused(t)){const t=2,r=10;i.fillStyle=ThemeSupport.ThemeSupport.instance().getComputedValue("--selected-group-border",this.contentElement),i.fillRect(0,e-t,t,n-s.style.padding+2*t),i.fillRect(0,e-t,r,t),i.fillRect(0,e+n-s.style.padding,r,t)}})),i.restore()}drawMarkers(e,t,i){const{entryStartTimes:s,entryLevels:r}=t;this.markerPositions.clear(),e.textBaseline="alphabetic",e.save(),e.beginPath();let n=-1,o=-1/0;for(let t=i.length-1;t>=0;--t){const a=i[t],l=this.dataProvider.entryTitle(a);if(!l)continue;const h=s[a],d=r[a];n!==d&&(o=-1/0);const c=Math.max(this.chartViewport.timeToPosition(h),o),p=this.levelToOffset(d),u=this.levelHeight(d),m=4,f=Math.ceil(UI.UIUtils.measureTextWidth(e,l))+2*m;o=c+f+1,n=d,this.markerPositions.set(a,{x:c,width:f}),e.fillStyle=this.dataProvider.entryColor(a),e.fillRect(c,p,f,u-1),e.fillStyle="white",e.fillText(l,c+m,p+u-this.textBaseline)}e.strokeStyle="rgba(0, 0, 0, 0.2)",e.stroke(),e.restore()}drawEventTitles(e,t,i,s){const r=this.chartViewport.timeToPixel(),n=this.textPadding;e.save(),e.beginPath();const{entryStartTimes:o,entryLevels:a}=t;for(let l=0;l<i.length;++l){const h=i[l],d=o[h],c=this.timeToPositionClipped(d),p=Math.min(this.#o(t,h),s),u=a[h],m=this.levelToOffset(u);let f=this.dataProvider.entryTitle(h);f&&f.length&&(e.font=this.#e,f=UI.UIUtils.trimTextMiddle(e,f,p-2*n));const g=this.chartViewport.timeToPosition(d),v=this.#n(t,h);this.dataProvider.decorateEntry(h,e,f,c,m,p,v,g,r)||f&&f.length&&(e.fillStyle=this.dataProvider.textColor(h),e.fillText(f,c+n,m+v-this.textBaseline))}e.restore()}forEachGroup(e){if(!this.rawTimelineData)return;const t=this.rawTimelineData.groups||[];if(!t.length)return;const i=this.groupOffsets;if(!i)return;const s=[{nestingLevel:-1,visible:!0}];for(let r=0;r<t.length;++r){const n=i[r],o=t[r];let a=!0,l=s[s.length-1];for(;l&&l.nestingLevel>=o.style.nestingLevel;)s.pop(),a=!1,l=s[s.length-1];l=s[s.length-1];const h=!!l&&l.visible,d=h&&(!this.isGroupCollapsible(r)||o.expanded);s.push({nestingLevel:o.style.nestingLevel,visible:Boolean(d)});const c=r===t.length-1?i[r+1]+o.style.padding:i[r+1];h&&e(n,r,o,a,c-n)}}forEachGroupInViewport(e){const t=this.chartViewport.scrollOffset();this.forEachGroup(((i,s,r,n,o)=>{i-r.style.padding>t+this.offsetHeight||i+o<t||e(i,s,r,n,o)}))}labelWidthForGroup(e,t){return UI.UIUtils.measureTextWidth(e,t.name)+this.expansionArrowIndent*(t.style.nestingLevel+1)+2*this.headerLabelXPadding}drawCollapsedOverviewForGroup(e,t,i){const s=new Common.SegmentedRange.SegmentedRange((function(e,t){return e.data===t.data&&e.end+.4>t.end?e:null})),r=this.chartViewport.windowLeftTime(),n=this.chartViewport.windowRightTime(),o=this.canvas.getContext("2d"),a=e.style.height;if(!this.rawTimelineData)return;const l=this.rawTimelineData.entryStartTimes,h=this.rawTimelineData.entryTotalTimes,d=this.chartViewport.timeToPixel();for(let c=e.startLevel;c<i;++c){const i=this.timelineLevels?this.timelineLevels[c]:[];let p=1/0;for(let c=Platform.ArrayUtilities.lowerBound(i,n,((e,t)=>e-l[t]))-1;c>=0;--c){const n=i[c],u=l[n],m=this.timeToPositionClipped(u),f=u+h[n];if(isNaN(f)||m>=p)continue;if(f<=r)break;p=m;const g=this.entryColorsCache?this.entryColorsCache[n]:"",v=this.timeToPositionClipped(f);if(e.style.useDecoratorsForOverview&&this.dataProvider.forceDecoration(n)){const e=this.chartViewport.timeToPosition(u),i=this.#o(this.rawTimelineData,n);o.beginPath(),o.fillStyle=g,o.fillRect(m,t,i,a-1),this.dataProvider.decorateEntry(n,o,"",m,t,i,a,e,d)}else s.append(new Common.SegmentedRange.Segment(m,v,g))}}const c=s.segments().slice().sort(((e,t)=>e.data.localeCompare(t.data)));let p;o.beginPath();for(let e=0;e<c.length;++e){const i=c[e];p!==c[e].data&&(o.fill(),o.beginPath(),p=c[e].data,o.fillStyle=p),o.rect(i.begin,t,i.end-i.begin,a)}o.fill()}drawFlowEvents(e,t,i){e.save();const s=window.devicePixelRatio,r=this.chartViewport.scrollOffset();e.scale(s,s),e.translate(0,-r),e.fillStyle="#7f5050",e.strokeStyle="#7f5050";const n=this.timelineData();if(!n)return;const o=Platform.ArrayUtilities.lowerBound(n.flowStartTimes,this.chartViewport.windowRightTime(),Platform.ArrayUtilities.DEFAULT_COMPARATOR);e.lineWidth=.5;for(let t=0;t<o;++t){if(!n.flowEndTimes[t]||n.flowEndTimes[t]<this.chartViewport.windowLeftTime())continue;const i=this.chartViewport.timeToPosition(n.flowStartTimes[t]),s=this.chartViewport.timeToPosition(n.flowEndTimes[t]),r=n.flowStartLevels[t],o=n.flowEndLevels[t],a=this.levelToOffset(r)+this.levelHeight(r)/2,l=this.levelToOffset(o)+this.levelHeight(o)/2,h=Math.min((s-i)/4,40),d=(l-a)/10,c=30,p=n.flowEndTimes[t]-n.flowStartTimes[t]<1?a:c+Math.max(0,a+d*(t%c)),u=[];u.push({x:i,y:a}),u.push({x:i+6,y:a}),u.push({x:i+h+12,y:a}),u.push({x:i+h,y:p}),u.push({x:i+2*h,y:p}),u.push({x:s-2*h,y:p}),u.push({x:s-h,y:p}),u.push({x:s-h-12,y:l}),u.push({x:s-6,y:l}),e.beginPath(),e.moveTo(u[0].x,u[0].y),e.lineTo(u[1].x,u[1].y),e.bezierCurveTo(u[2].x,u[2].y,u[3].x,u[3].y,u[4].x,u[4].y),e.lineTo(u[5].x,u[5].y),e.bezierCurveTo(u[6].x,u[6].y,u[7].x,u[7].y,u[8].x,u[8].y),e.stroke(),e.beginPath(),e.arc(i,a,2,-Math.PI/2,Math.PI/2,!1),e.fill(),e.beginPath(),e.moveTo(s,l),e.lineTo(s-6,l-3),e.lineTo(s-6,l+3),e.fill()}e.restore()}drawMarkerLines(){const e=this.timelineData();if(!e)return;const t=e.markers,i=this.markerIndexBeforeTime(this.minimumBoundary()),s=this.maximumBoundary(),r=this.chartViewport.timeToPixel(),n=this.canvas.getContext("2d");n.save();const o=window.devicePixelRatio;n.scale(o,o),n.translate(0,3);const a=HeaderHeight-1;for(let e=i;e<t.length;e++){const i=t[e].startTime();if(i>s)break;t[e].draw(n,this.chartViewport.timeToPosition(i),a,r)}n.restore()}updateMarkerHighlight(){const e=this.markerHighlighElement;e.parentElement&&e.remove();const t=this.highlightedMarkerIndex;if(-1===t)return;const i=this.timelineData();if(!i)return;const s=i.markers[t],r=this.timeToPositionClipped(s.startTime());UI.Tooltip.Tooltip.install(e,s.title()||"");const n=e.style;n.left=r+"px",n.backgroundColor=s.color(),this.viewportElement.appendChild(e)}processTimelineData(e){if(!e)return this.timelineLevels=null,this.visibleLevelOffsets=null,this.visibleLevels=null,this.groupOffsets=null,this.rawTimelineData=null,this.forceDecorationCache=null,this.entryColorsCache=null,this.rawTimelineDataLength=0,this.selectedGroup=-1,this.keyboardFocusedGroup=-1,void this.flameChartDelegate.updateSelectedGroup(this,null);this.rawTimelineData=e,this.rawTimelineDataLength=e.entryStartTimes.length,this.forceDecorationCache=new Int8Array(this.rawTimelineDataLength),this.entryColorsCache=new Array(this.rawTimelineDataLength);for(let e=0;e<this.rawTimelineDataLength;++e)this.forceDecorationCache[e]=this.dataProvider.forceDecoration(e)?1:0,this.entryColorsCache[e]=this.dataProvider.entryColor(e);const t=new Uint32Array(this.dataProvider.maxStackDepth()+1);for(let i=0;i<e.entryLevels.length;++i)++t[e.entryLevels[i]];const i=new Array(t.length);for(let e=0;e<i.length;++e)i[e]=new Uint32Array(t[e]),t[e]=0;for(let s=0;s<e.entryLevels.length;++s){const r=e.entryLevels[s];i[r][t[r]++]=s}this.timelineLevels=i;const s=this.rawTimelineData.groups||[];for(let e=0;e<s.length;++e){const t=this.groupExpansionState[s[e].name];void 0!==t&&(s[e].expanded=t)}this.updateLevelPositions(),this.updateHeight(),this.selectedGroup=e.selectedGroup?s.indexOf(e.selectedGroup):-1,this.keyboardFocusedGroup=this.selectedGroup,this.flameChartDelegate.updateSelectedGroup(this,e.selectedGroup)}updateLevelPositions(){const e=this.dataProvider.maxStackDepth(),t=this.rawTimelineData&&this.rawTimelineData.groups||[];this.visibleLevelOffsets=new Uint32Array(e+1),this.visibleLevelHeights=new Uint32Array(e),this.visibleLevels=new Uint16Array(e),this.groupOffsets=new Uint32Array(t.length+1);let i=-1,s=this.rulerEnabled?HeaderHeight+2:2,r=!0;const n=[{nestingLevel:-1,visible:!0}],o=Math.max(e,t.length?t[t.length-1].startLevel+1:0);let a;for(a=0;a<o;++a){let o,l=!0;for(;i<t.length-1&&a===t[i+1].startLevel;){++i,o=t[i].style;let e=!0,a=n[n.length-1];for(;a&&a.nestingLevel>=o.nestingLevel;)n.pop(),e=!1,a=n[n.length-1];const h=!(i>=0&&this.isGroupCollapsible(i))||t[i].expanded;a=n[n.length-1],l=!!a&&a.visible,r=Boolean(h)&&l,n.push({nestingLevel:o.nestingLevel,visible:r}),l&&(s+=e?0:o.padding),this.groupOffsets[i]=s,l&&!o.shareHeaderLine&&(s+=o.height)}if(a>=e)continue;const h=i>=0&&a===t[i].startLevel,d=l&&(r||h&&t[i].style.useFirstLineForOverview);let c;if(i>=0){const e=t[i],s=e.style;c=h&&!s.shareHeaderLine||s.collapsible&&!e.expanded?s.height:s.itemsHeight||this.barHeight}else c=this.barHeight;this.visibleLevels[a]=d?1:0,this.visibleLevelOffsets[a]=s,this.visibleLevelHeights[a]=c,(d||l&&o&&o.shareHeaderLine&&h)&&(s+=this.visibleLevelHeights[a])}i>=0&&(this.groupOffsets[i+1]=s),this.visibleLevelOffsets[a]=s}isGroupCollapsible(e){if(!this.rawTimelineData)return;const t=this.rawTimelineData.groups||[],i=t[e].style;if(!i.shareHeaderLine||!i.collapsible)return Boolean(i.collapsible);const s=e+1>=t.length;if(!s&&t[e+1].style.nestingLevel>i.nestingLevel)return!0;return(s?this.dataProvider.maxStackDepth():t[e+1].startLevel)!==t[e].startLevel+1||i.height!==i.itemsHeight}setSelectedEntry(e){this.selectedEntryIndex!==e&&(-1!==e&&this.chartViewport.hideRangeSelection(),this.selectedEntryIndex=e,this.revealEntry(e),this.updateElementPosition(this.selectedElement,this.selectedEntryIndex))}updateElementPosition(e,t){if(e.classList.add("hidden"),-1===t)return;const i=this.timelineData();if(!i)return;const s=i.entryStartTimes[t],r=i.entryTotalTimes[t];let n=0,o=0,a=!0;if(Number.isNaN(r)){const e=this.markerPositions.get(t);e?(n=e.x,o=e.width):a=!1}else n=this.chartViewport.timeToPosition(s),o=r*this.chartViewport.timeToPixel();if(n+o<=0||n>=this.offsetWidth)return;const l=n+o/2;o=Math.max(o,2),n=l-o/2;const h=i.entryLevels[t],d=this.levelToOffset(h)-this.chartViewport.scrollOffset(),c=this.levelHeight(h),p=e.style;p.left=n+"px",p.top=d+"px",p.width=o+"px",p.height=c-1+"px",e.classList.toggle("hidden",!a),this.viewportElement.appendChild(e)}timeToPositionClipped(e){return Platform.NumberUtilities.clamp(this.chartViewport.timeToPosition(e),0,this.offsetWidth)}levelToOffset(e){if(!this.visibleLevelOffsets)throw new Error("No visible level offsets");return this.visibleLevelOffsets[e]}levelHeight(e){if(!this.visibleLevelHeights)throw new Error("No visible level heights");return this.visibleLevelHeights[e]}updateBoundaries(){this.totalTime=this.dataProvider.totalTime(),this.minimumBoundaryInternal=this.dataProvider.minimumBoundary(),this.chartViewport.setBoundaries(this.minimumBoundaryInternal,this.totalTime)}updateHeight(){const e=this.levelToOffset(this.dataProvider.maxStackDepth())+2;this.chartViewport.setContentHeight(e)}onResize(){this.scheduleUpdate()}update(){this.timelineData()&&(this.resetCanvas(),this.updateHeight(),this.updateBoundaries(),this.draw(),this.chartViewport.isDragging()||this.updateHighlight())}reset(){this.chartViewport.reset(),this.rawTimelineData=null,this.rawTimelineDataLength=0,this.highlightedMarkerIndex=-1,this.highlightedEntryIndex=-1,this.selectedEntryIndex=-1,this.chartViewport.scheduleUpdate()}scheduleUpdate(){this.chartViewport.scheduleUpdate()}enabled(){return 0!==this.rawTimelineDataLength}computePosition(e){return this.chartViewport.timeToPosition(e)}formatValue(e,t){return this.dataProvider.formatValue(e-this.zeroTime(),t)}maximumBoundary(){return TraceEngine.Types.Timing.MilliSeconds(this.chartViewport.windowRightTime())}minimumBoundary(){return TraceEngine.Types.Timing.MilliSeconds(this.chartViewport.windowLeftTime())}zeroTime(){return TraceEngine.Types.Timing.MilliSeconds(this.dataProvider.minimumBoundary())}boundarySpan(){return TraceEngine.Types.Timing.MilliSeconds(this.maximumBoundary()-this.minimumBoundary())}}export const HeaderHeight=15;export const MinimalTimeWindowMs=.5;const decorationDrawOrder={CANDY:1,WARNING_TRIANGLE:2};export function sortDecorationsForRenderingOrder(e){e.sort(((e,t)=>decorationDrawOrder[e.type]-decorationDrawOrder[t.type]))}export class FlameChartTimelineData{entryLevels;entryTotalTimes;entryStartTimes;entryDecorations;groups;markers;flowStartTimes;flowStartLevels;flowEndTimes;flowEndLevels;selectedGroup;constructor(e,t,i,s,r=[]){this.entryLevels=e,this.entryTotalTimes=t,this.entryStartTimes=i,this.entryDecorations=r,this.groups=s||[],this.markers=[],this.flowStartTimes=[],this.flowStartLevels=[],this.flowEndTimes=[],this.flowEndLevels=[],this.selectedGroup=null}static create(e){return new FlameChartTimelineData(e.entryLevels,e.entryTotalTimes,e.entryStartTimes,e.groups,e.entryDecorations||[])}static createEmpty(){return new FlameChartTimelineData([],[],[],[])}}export var Events;!function(e){e.CanvasFocused="CanvasFocused",e.EntryInvoked="EntryInvoked",e.EntrySelected="EntrySelected",e.EntryHighlighted="EntryHighlighted"}(Events||(Events={}));