From 0c35081c23a864d474dfb8ff75d539747979c4ae Mon Sep 17 00:00:00 2001 From: Andrew Levans Date: Tue, 7 May 2024 13:53:04 -0500 Subject: [PATCH 1/4] Compute track-shell-width as needed --- ui/src/frontend/css_constants.ts | 2 +- ui/src/frontend/flow_events_renderer.ts | 7 +++-- ui/src/frontend/gridline_helper.ts | 9 +++--- ui/src/frontend/notes_panel.ts | 32 +++++++++++----------- ui/src/frontend/overview_timeline_panel.ts | 16 +++++------ ui/src/frontend/panel_container.ts | 6 ++-- ui/src/frontend/tickmark_panel.ts | 20 +++++++------- ui/src/frontend/time_axis_panel.ts | 14 +++++----- ui/src/frontend/time_selection_panel.ts | 28 ++++++++++--------- ui/src/frontend/track_panel.ts | 13 +++++---- ui/src/frontend/vertical_line_helper.ts | 4 +-- ui/src/frontend/viewer_page.ts | 18 ++++++------ 12 files changed, 88 insertions(+), 81 deletions(-) diff --git a/ui/src/frontend/css_constants.ts b/ui/src/frontend/css_constants.ts index f93c613bc4..5a930e4ae3 100644 --- a/ui/src/frontend/css_constants.ts +++ b/ui/src/frontend/css_constants.ts @@ -45,7 +45,7 @@ export function getCssStr(prop: string): string { return window.getComputedStyle(doc).getPropertyValue(prop).trim(); } -function getCssNum(prop: string): number|undefined { +export function getCssNum(prop: string): number|undefined { const str = getCssStr(prop); if (str === undefined) return undefined; const match = str.match(/^\W*(\d+)px(|\!important')$/); diff --git a/ui/src/frontend/flow_events_renderer.ts b/ui/src/frontend/flow_events_renderer.ts index c511758975..79f5639996 100644 --- a/ui/src/frontend/flow_events_renderer.ts +++ b/ui/src/frontend/flow_events_renderer.ts @@ -13,7 +13,7 @@ // limitations under the License. import {TPTime} from '../common/time'; -import {TRACK_SHELL_WIDTH} from './css_constants'; +import {getCssNum} from './css_constants'; import {ALL_CATEGORIES, getFlowCategories} from './flow_events_panel'; import {Flow, FlowPoint, globals} from './globals'; import {PanelVNode} from './panel'; @@ -156,8 +156,9 @@ export class FlowEventsRenderer { render(ctx: CanvasRenderingContext2D, args: FlowEventsRendererArgs) { ctx.save(); - ctx.translate(TRACK_SHELL_WIDTH, 0); - ctx.rect(0, 0, args.canvasWidth - TRACK_SHELL_WIDTH, args.canvasHeight); + const trackShellWidth = getCssNum('--track-shell-width') || 0; + ctx.translate(trackShellWidth, 0); + ctx.rect(0, 0, args.canvasWidth - trackShellWidth, args.canvasHeight); ctx.clip(); globals.connectedFlows.forEach((flow) => { diff --git a/ui/src/frontend/gridline_helper.ts b/ui/src/frontend/gridline_helper.ts index a92d504be5..fcf3e07408 100644 --- a/ui/src/frontend/gridline_helper.ts +++ b/ui/src/frontend/gridline_helper.ts @@ -16,7 +16,7 @@ import {assertTrue} from '../base/logging'; import {Span, tpDurationToSeconds} from '../common/time'; import {TPDuration, TPTime, TPTimeSpan} from '../common/time'; -import {TRACK_SHELL_WIDTH, getCssStr} from './css_constants'; +import {getCssNum, getCssStr} from './css_constants'; import {globals} from './globals'; import {TimeScale} from './time_scale'; @@ -216,9 +216,10 @@ export function drawGridLines( const {earliest, latest} = globals.frontendLocalState.visibleWindow; const span = new TPTimeSpan(earliest, latest); - if (width > TRACK_SHELL_WIDTH && span.duration > 0n) { - const maxMajorTicks = getMaxMajorTicks(width - TRACK_SHELL_WIDTH); - const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, width); + const trackShellWidth = getCssNum('--track-shell-width') || 0; + if (width > trackShellWidth && span.duration > 0n) { + const maxMajorTicks = getMaxMajorTicks(width - trackShellWidth); + const map = timeScaleForVisibleWindow(trackShellWidth, width); for (const {type, time} of new TickGenerator( span, maxMajorTicks, globals.state.traceTime.start)) { const px = Math.floor(map.tpTimeToPx(time)); diff --git a/ui/src/frontend/notes_panel.ts b/ui/src/frontend/notes_panel.ts index c2cfc857a9..77624c706d 100644 --- a/ui/src/frontend/notes_panel.ts +++ b/ui/src/frontend/notes_panel.ts @@ -26,7 +26,7 @@ import { bottomTabRegistry, NewBottomTabArgs, } from './bottom_tab'; -import {getCssStr, TRACK_SHELL_WIDTH} from './css_constants'; +import {getCssNum, getCssStr} from './css_constants'; import {PerfettoMouseEvent} from './events'; import {globals} from './globals'; import { @@ -61,11 +61,11 @@ export class NotesPanel extends Panel { oncreate({dom}: m.CVnodeDOM) { dom.addEventListener('mousemove', (e: Event) => { - this.hoveredX = (e as PerfettoMouseEvent).layerX - TRACK_SHELL_WIDTH; + this.hoveredX = (e as PerfettoMouseEvent).layerX - (getCssNum('--track-shell-width') || 0); globals.rafScheduler.scheduleRedraw(); }, {passive: true}); dom.addEventListener('mouseenter', (e: Event) => { - this.hoveredX = (e as PerfettoMouseEvent).layerX - TRACK_SHELL_WIDTH; + this.hoveredX = (e as PerfettoMouseEvent).layerX - (getCssNum('--track-shell-width') || 0); globals.rafScheduler.scheduleRedraw(); }); dom.addEventListener('mouseout', () => { @@ -82,11 +82,11 @@ export class NotesPanel extends Panel { '.notes-panel', { onclick: (e: PerfettoMouseEvent) => { - this.onClick(e.layerX - TRACK_SHELL_WIDTH, e.layerY); + this.onClick(e.layerX - (getCssNum('--track-shell-width') || 0), e.layerY); e.stopPropagation(); }, oncontextmenu: (e: PerfettoMouseEvent)=>{ - this.onRightClick(e.layerX - TRACK_SHELL_WIDTH, e.layerY); + this.onRightClick(e.layerX - (getCssNum('--track-shell-width') || 0), e.layerY); e.stopPropagation(); }, }, @@ -145,20 +145,20 @@ export class NotesPanel extends Panel { renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) { let aNoteIsHovered = false; - + const trackShellWidth = (getCssNum('--track-shell-width') || 0); ctx.fillStyle = getCssStr('--main-foreground-color'); - ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height); + ctx.fillRect(trackShellWidth - 2, 0, 2, size.height); ctx.save(); ctx.beginPath(); - ctx.rect(TRACK_SHELL_WIDTH, 0, size.width - TRACK_SHELL_WIDTH, size.height); + ctx.rect(trackShellWidth, 0, size.width - trackShellWidth, size.height); ctx.clip(); const span = globals.frontendLocalState.visibleWindow.timestampSpan; const {visibleTimeScale} = globals.frontendLocalState; - if (size.width > TRACK_SHELL_WIDTH && span.duration > 0n) { - const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH); - const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width); + if (size.width > trackShellWidth && span.duration > 0n) { + const maxMajorTicks = getMaxMajorTicks(size.width - trackShellWidth); + const map = timeScaleForVisibleWindow(trackShellWidth, size.width); for (const {type, time} of new TickGenerator( span, maxMajorTicks, globals.state.traceTime.start)) { const px = Math.floor(map.tpTimeToPx(time)); @@ -190,7 +190,7 @@ export class NotesPanel extends Panel { ((selection.kind === 'NOTE' && selection.id === note.id) || (selection.kind === 'AREA' && selection.noteId === note.id)); const x = visibleTimeScale.tpTimeToPx(timestamp); - const left = Math.floor(x + TRACK_SHELL_WIDTH); + const left = Math.floor(x + trackShellWidth); // Draw flag or marker. if (note.noteType === 'AREA') { @@ -199,7 +199,7 @@ export class NotesPanel extends Panel { ctx, left, Math.floor( - visibleTimeScale.tpTimeToPx(area.end) + TRACK_SHELL_WIDTH), + visibleTimeScale.tpTimeToPx(area.end) + trackShellWidth), note.color, isSelected); } else { @@ -230,7 +230,7 @@ export class NotesPanel extends Panel { if (span.contains(timestamp)) { globals.dispatch(Actions.setHoveredNoteTimestamp({ts: timestamp})); const x = visibleTimeScale.tpTimeToPx(timestamp); - const left = Math.floor(x + TRACK_SHELL_WIDTH); + const left = Math.floor(x + trackShellWidth); this.drawFlag(ctx, left, size.height, '#aaa', /* fill */ true); } } @@ -245,7 +245,7 @@ export class NotesPanel extends Panel { ctx.strokeStyle = color; const topOffset = 10; // Don't draw in the track shell section. - if (x >= globals.frontendLocalState.windowSpan.start + TRACK_SHELL_WIDTH) { + if (x >= globals.frontendLocalState.windowSpan.start + (getCssNum('--track-shell-width') || 0)) { // Draw left triangle. ctx.beginPath(); ctx.moveTo(x, topOffset); @@ -266,7 +266,7 @@ export class NotesPanel extends Panel { // Start line after track shell section, join triangles. const startDraw = Math.max( - x, globals.frontendLocalState.windowSpan.start + TRACK_SHELL_WIDTH); + x, globals.frontendLocalState.windowSpan.start + (getCssNum('--track-shell-width') || 0)); ctx.beginPath(); ctx.moveTo(startDraw, topOffset); ctx.lineTo(xEnd, topOffset); diff --git a/ui/src/frontend/overview_timeline_panel.ts b/ui/src/frontend/overview_timeline_panel.ts index e4632bbe7c..569ae237b5 100644 --- a/ui/src/frontend/overview_timeline_panel.ts +++ b/ui/src/frontend/overview_timeline_panel.ts @@ -23,7 +23,7 @@ import { import { OVERVIEW_TIMELINE_NON_VISIBLE_COLOR, - TRACK_SHELL_WIDTH, + getCssNum, getCssStr, } from './css_constants'; import {BorderDragStrategy} from './drag/border_drag_strategy'; @@ -59,7 +59,7 @@ export class OverviewTimelinePanel extends Panel { this.width = newWidth; this.traceTime = globals.stateTraceTimeTP(); const traceTime = globals.stateTraceTime(); - const pxSpan = new PxSpan(TRACK_SHELL_WIDTH, this.width); + const pxSpan = new PxSpan((getCssNum('--track-shell-width') || 0), this.width); this.timeScale = TimeScale.fromHPTimeSpan(traceTime, pxSpan); if (this.gesture === undefined) { this.gesture = new DragGestureHandler( @@ -92,12 +92,12 @@ export class OverviewTimelinePanel extends Panel { const headerHeight = 20; const tracksHeight = size.height - headerHeight; - if (size.width > TRACK_SHELL_WIDTH && this.traceTime.duration > 0n) { - const maxMajorTicks = getMaxMajorTicks(this.width - TRACK_SHELL_WIDTH); + if (size.width > (getCssNum('--track-shell-width') || 0) && this.traceTime.duration > 0n) { + const maxMajorTicks = getMaxMajorTicks(this.width - (getCssNum('--track-shell-width') || 0)); const tickGen = new TickGenerator( this.traceTime, maxMajorTicks, globals.state.traceTime.start); ctx.fillStyle = getCssStr('--overview-background-color'); - ctx.fillRect(TRACK_SHELL_WIDTH, headerHeight, this.width, size.height - headerHeight); + ctx.fillRect((getCssNum('--track-shell-width') || 0), headerHeight, this.width, size.height - headerHeight); // Draw time labels on the top header. ctx.font = '10px Roboto Condensed'; ctx.fillStyle = getCssStr('--main-foreground-color'); @@ -146,9 +146,9 @@ export class OverviewTimelinePanel extends Panel { ctx.fillStyle = OVERVIEW_TIMELINE_NON_VISIBLE_COLOR; ctx.fillRect( - TRACK_SHELL_WIDTH - 1, + (getCssNum('--track-shell-width') || 0) - 1, headerHeight, - vizStartPx - TRACK_SHELL_WIDTH, + vizStartPx - (getCssNum('--track-shell-width') || 0), tracksHeight); ctx.fillRect(vizEndPx, headerHeight, this.width - vizEndPx, tracksHeight); @@ -186,7 +186,7 @@ export class OverviewTimelinePanel extends Panel { if (OverviewTimelinePanel.inBorderRange(x, startBound) || OverviewTimelinePanel.inBorderRange(x, endBound)) { return 'ew-resize'; - } else if (x < TRACK_SHELL_WIDTH) { + } else if (x < (getCssNum('--track-shell-width') || 0)) { return 'default'; } else if (x < startBound || endBound < x) { return 'crosshair'; diff --git a/ui/src/frontend/panel_container.ts b/ui/src/frontend/panel_container.ts index dd33b2ba24..02267da6a6 100644 --- a/ui/src/frontend/panel_container.ts +++ b/ui/src/frontend/panel_container.ts @@ -18,7 +18,7 @@ import {assertExists, assertFalse, assertTrue} from '../base/logging'; import { TOPBAR_HEIGHT, - TRACK_SHELL_WIDTH, + getCssNum, getCssStr, } from './css_constants'; import { @@ -326,7 +326,7 @@ export class PanelContainer implements m.ClassComponent { this.repositionCanvas(); if (this.attrs.kind === 'TRACKS') { globals.frontendLocalState.updateLocalLimits( - 0, this.parentWidth - TRACK_SHELL_WIDTH); + 0, this.parentWidth - (getCssNum('--track-shell-width') || 0)); } this.redrawCanvas(); } @@ -508,7 +508,7 @@ export class PanelContainer implements m.ClassComponent { this.ctx.lineWidth = 1; const canvasYStart = Math.floor(this.scrollTop - this.getCanvasOverdrawHeightPerSide()); - this.ctx.translate(TRACK_SHELL_WIDTH, -canvasYStart); + this.ctx.translate((getCssNum('--track-shell-width') || 0), -canvasYStart); this.ctx.strokeRect( startX, selectedTracksMaxY, diff --git a/ui/src/frontend/tickmark_panel.ts b/ui/src/frontend/tickmark_panel.ts index 5663d21784..563b6186c4 100644 --- a/ui/src/frontend/tickmark_panel.ts +++ b/ui/src/frontend/tickmark_panel.ts @@ -16,7 +16,7 @@ import m from 'mithril'; import {TPTimeSpan} from '../common/time'; -import {getCssStr, TRACK_SHELL_WIDTH} from './css_constants'; +import {getCssNum, getCssStr} from './css_constants'; import {globals} from './globals'; import { getMaxMajorTicks, @@ -61,19 +61,19 @@ export class TickmarkPanel extends Panel { renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) { this.indicators = []; const {visibleTimeScale} = globals.frontendLocalState; - + const trackShellWidth = (getCssNum('--track-shell-width') || 0); ctx.fillStyle = getCssStr('--main-foreground-color'); - ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height); + ctx.fillRect(trackShellWidth - 2, 0, 2, size.height); ctx.save(); ctx.beginPath(); - ctx.rect(TRACK_SHELL_WIDTH, 0, size.width - TRACK_SHELL_WIDTH, size.height); + ctx.rect(trackShellWidth, 0, size.width - trackShellWidth, size.height); ctx.clip(); const visibleSpan = globals.frontendLocalState.visibleWindow.timestampSpan; - if (size.width > TRACK_SHELL_WIDTH && visibleSpan.duration > 0n) { - const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH); - const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width); + if (size.width > trackShellWidth && visibleSpan.duration > 0n) { + const maxMajorTicks = getMaxMajorTicks(size.width - trackShellWidth); + const map = timeScaleForVisibleWindow(trackShellWidth, size.width); for (const {type, time} of new TickGenerator( visibleSpan, maxMajorTicks, globals.state.traceTime.start)) { const px = Math.floor(map.tpTimeToPx(time)); @@ -92,8 +92,8 @@ export class TickmarkPanel extends Panel { continue; } const rectStart = - Math.max(visibleTimeScale.tpTimeToPx(tStart), 0) + TRACK_SHELL_WIDTH; - const rectEnd = visibleTimeScale.tpTimeToPx(tEnd) + TRACK_SHELL_WIDTH; + Math.max(visibleTimeScale.tpTimeToPx(tStart), 0) + trackShellWidth; + const rectEnd = visibleTimeScale.tpTimeToPx(tEnd) + trackShellWidth; ctx.fillStyle = '#dcdc3b'; const x = Math.floor(rectStart); const w = Math.ceil(rectEnd - rectStart); @@ -108,7 +108,7 @@ export class TickmarkPanel extends Panel { if (index !== -1) { const start = globals.currentSearchResults.tsStarts[index]; const triangleStart = - Math.max(visibleTimeScale.tpTimeToPx(start), 0) + TRACK_SHELL_WIDTH; + Math.max(visibleTimeScale.tpTimeToPx(start), 0) + trackShellWidth; ctx.fillStyle = getCssStr('--main-foreground-color'); ctx.strokeStyle = getCssStr('--main-background-color'); ctx.beginPath(); diff --git a/ui/src/frontend/time_axis_panel.ts b/ui/src/frontend/time_axis_panel.ts index dc6800e93c..306086f204 100644 --- a/ui/src/frontend/time_axis_panel.ts +++ b/ui/src/frontend/time_axis_panel.ts @@ -19,7 +19,7 @@ import { tpTimeToString, } from '../common/time'; -import {getCssStr, TRACK_SHELL_WIDTH} from './css_constants'; +import {getCssNum, getCssStr} from './css_constants'; import {globals} from './globals'; import { getMaxMajorTicks, @@ -41,17 +41,17 @@ export class TimeAxisPanel extends Panel { const startTime = tpTimeToString(globals.state.traceTime.start); ctx.fillText(startTime + ' +', 6, 11); - + const trackShellWidth = (getCssNum('--track-shell-width') || 0); ctx.save(); ctx.beginPath(); - ctx.rect(TRACK_SHELL_WIDTH, 0, size.width - TRACK_SHELL_WIDTH, size.height); + ctx.rect(trackShellWidth, 0, size.width - trackShellWidth, size.height); ctx.clip(); // Draw time axis. const span = globals.frontendLocalState.visibleWindow.timestampSpan; - if (size.width > TRACK_SHELL_WIDTH && span.duration > 0n) { - const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH); - const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width); + if (size.width > trackShellWidth && span.duration > 0n) { + const maxMajorTicks = getMaxMajorTicks(size.width - trackShellWidth); + const map = timeScaleForVisibleWindow(trackShellWidth, size.width); const tickGen = new TickGenerator(span, maxMajorTicks, globals.state.traceTime.start); for (const {type, time} of tickGen) { @@ -66,6 +66,6 @@ export class TimeAxisPanel extends Panel { ctx.restore(); - ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height); + ctx.fillRect(trackShellWidth - 2, 0, 2, size.height); } } diff --git a/ui/src/frontend/time_selection_panel.ts b/ui/src/frontend/time_selection_panel.ts index 24ebb735d6..a79150b0ab 100644 --- a/ui/src/frontend/time_selection_panel.ts +++ b/ui/src/frontend/time_selection_panel.ts @@ -22,8 +22,8 @@ import { } from '../common/time'; import { + getCssNum, getCssStr, - TRACK_SHELL_WIDTH, } from './css_constants'; import {globals} from './globals'; import { @@ -133,17 +133,18 @@ export class TimeSelectionPanel extends Panel { renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) { ctx.fillStyle = getCssStr('--main-foreground-color'); - ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height); + const trackShellWidth = (getCssNum('--track-shell-width') || 0); + ctx.fillRect(trackShellWidth - 2, 0, 2, size.height); ctx.save(); ctx.beginPath(); - ctx.rect(TRACK_SHELL_WIDTH, 0, size.width - TRACK_SHELL_WIDTH, size.height); + ctx.rect(trackShellWidth, 0, size.width - trackShellWidth, size.height); ctx.clip(); const span = globals.frontendLocalState.visibleWindow.timestampSpan; - if (size.width > TRACK_SHELL_WIDTH && span.duration > 0n) { - const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH); - const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width); + if (size.width > trackShellWidth && span.duration > 0n) { + const maxMajorTicks = getMaxMajorTicks(size.width - trackShellWidth); + const map = timeScaleForVisibleWindow(trackShellWidth, size.width); for (const {type, time} of new TickGenerator( span, maxMajorTicks, globals.state.traceTime.start)) { const px = Math.floor(map.tpTimeToPx(time)); @@ -152,7 +153,7 @@ export class TimeSelectionPanel extends Panel { } } } - + const localArea = globals.frontendLocalState.selectedArea; const selection = globals.state.currentSelection; if (localArea !== undefined) { @@ -165,11 +166,11 @@ export class TimeSelectionPanel extends Panel { const end = BigintMath.max(selectedArea.start, selectedArea.end); this.renderSpan(ctx, size, new TPTimeSpan(start, end)); } - + if (globals.state.hoverCursorTimestamp !== -1n) { this.renderHover(ctx, size, globals.state.hoverCursorTimestamp); } - + for (const note of Object.values(globals.state.notes)) { const noteIsSelected = selection !== null && selection.kind === 'AREA' && selection.noteId === note.id; @@ -186,7 +187,7 @@ export class TimeSelectionPanel extends Panel { renderHover(ctx: CanvasRenderingContext2D, size: PanelSize, ts: TPTime) { const {visibleTimeScale} = globals.frontendLocalState; const xPos = - TRACK_SHELL_WIDTH + Math.floor(visibleTimeScale.tpTimeToPx(ts)); + (getCssNum('--track-shell-width') || 0) + Math.floor(visibleTimeScale.tpTimeToPx(ts)); const offsetTime = tpTimeToString(ts - globals.state.traceTime.start); const timeFromStart = tpTimeToString(ts); const label = `${offsetTime} (${timeFromStart})`; @@ -202,7 +203,7 @@ export class TimeSelectionPanel extends Panel { drawHBar( ctx, { - x: TRACK_SHELL_WIDTH + xLeft, + x: (getCssNum('--track-shell-width') || 0) + xLeft, y: 0, width: xRight - xLeft, height: size.height, @@ -212,10 +213,11 @@ export class TimeSelectionPanel extends Panel { } private bounds(size: PanelSize): BBox { + const trackShellWidth = (getCssNum('--track-shell-width') || 0); return { - x: TRACK_SHELL_WIDTH, + x: trackShellWidth, y: 0, - width: size.width - TRACK_SHELL_WIDTH, + width: size.width - trackShellWidth, height: size.height, }; } diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts index fe1f67bb35..a40807eec3 100644 --- a/ui/src/frontend/track_panel.ts +++ b/ui/src/frontend/track_panel.ts @@ -19,7 +19,7 @@ import {Actions} from '../common/actions'; import {TrackGroupState, TrackState} from '../common/state'; import {TPTime} from '../common/time'; -import {TRACK_SHELL_WIDTH, getCssStr} from './css_constants'; +import {getCssNum, getCssStr} from './css_constants'; import {PerfettoMouseEvent} from './events'; import {globals} from './globals'; import {drawGridLines} from './gridline_helper'; @@ -339,7 +339,7 @@ export class TrackContent implements m.ClassComponent { { onmousemove: (e: PerfettoMouseEvent) => { attrs.track.onMouseMove( - {x: e.layerX - TRACK_SHELL_WIDTH, y: e.layerY}); + {x: e.layerX - (getCssNum('--track-shell-width') || 0), y: e.layerY}); globals.rafScheduler.scheduleRedraw(); }, onmouseout: () => { @@ -372,7 +372,7 @@ export class TrackContent implements m.ClassComponent { } // Returns true if something was selected, so stop propagation. if (attrs.track.onMouseClick( - {x: e.layerX - TRACK_SHELL_WIDTH, y: e.layerY})) { + {x: e.layerX - (getCssNum('--track-shell-width') || 0), y: e.layerY})) { e.stopPropagation(); } globals.rafScheduler.scheduleRedraw(); @@ -506,7 +506,7 @@ export class TrackPanel extends Panel { if (selectedArea.tracks.includes(trackState.id)) { ctx.fillStyle = getCssStr('--selection-fill-color'); ctx.fillRect( - visibleTimeScale.tpTimeToPx(selectedArea.start) + TRACK_SHELL_WIDTH, + visibleTimeScale.tpTimeToPx(selectedArea.start) + (getCssNum('--track-shell-width') || 0), 0, visibleTimeScale.durationToPx(selectedAreaDuration), size.height); @@ -519,9 +519,10 @@ export class TrackPanel extends Panel { // If we have vsync data, render columns under the track and // under the grid lines painted next const vsync = getActiveVsyncData(); + const trackShellWidth = (getCssNum('--track-shell-width') || 0); if (vsync) { ctx.save(); - ctx.translate(TRACK_SHELL_WIDTH, 0); + ctx.translate(trackShellWidth, 0); renderVsyncColumns(ctx, size.height, vsync); ctx.restore(); } @@ -531,7 +532,7 @@ export class TrackPanel extends Panel { size.width, size.height); - ctx.translate(TRACK_SHELL_WIDTH, 0); + ctx.translate(trackShellWidth, 0); if (this.track !== undefined) { this.track.render(ctx); } diff --git a/ui/src/frontend/vertical_line_helper.ts b/ui/src/frontend/vertical_line_helper.ts index 353d166cb8..20bdb1b3e9 100644 --- a/ui/src/frontend/vertical_line_helper.ts +++ b/ui/src/frontend/vertical_line_helper.ts @@ -13,7 +13,7 @@ // limitations under the License. import {TPTime} from '../common/time'; -import {TRACK_SHELL_WIDTH} from './css_constants'; +import {getCssNum} from './css_constants'; import {TimeScale} from './time_scale'; export function drawVerticalLineAtTime( @@ -23,7 +23,7 @@ export function drawVerticalLineAtTime( height: number, color: string, lineWidth = 2) { - const xPos = TRACK_SHELL_WIDTH + Math.floor(timeScale.tpTimeToPx(time)); + const xPos = (getCssNum('--track-shell-width') || 0) + Math.floor(timeScale.tpTimeToPx(time)); drawVerticalLine(ctx, xPos, height, color, lineWidth); } diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts index 3d33e55684..b563081088 100644 --- a/ui/src/frontend/viewer_page.ts +++ b/ui/src/frontend/viewer_page.ts @@ -19,7 +19,7 @@ import {clamp} from '../base/math_utils'; import {Actions} from '../common/actions'; import {featureFlags} from '../common/feature_flags'; -import {TOPBAR_HEIGHT, TRACK_SHELL_WIDTH} from './css_constants'; +import {TOPBAR_HEIGHT, getCssNum} from './css_constants'; import {DetailsPanel} from './details_panel'; import {globals} from './globals'; import {NotesPanel} from './notes_panel'; @@ -57,7 +57,7 @@ function onTimeRangeBoundary(mousePos: number): 'START'|'END'|null { const {visibleTimeScale} = globals.frontendLocalState; const start = visibleTimeScale.tpTimeToPx(area.start); const end = visibleTimeScale.tpTimeToPx(area.end); - const startDrag = mousePos - TRACK_SHELL_WIDTH; + const startDrag = mousePos - (getCssNum('--track-shell-width') || 0); const startDistance = Math.abs(start - startDrag); const endDistance = Math.abs(end - startDrag); const range = 3 * window.devicePixelRatio; @@ -104,7 +104,7 @@ class TraceViewer implements m.ClassComponent { const rect = vnode.dom.getBoundingClientRect(); frontendLocalState.updateLocalLimits( 0, - rect.width - TRACK_SHELL_WIDTH - + rect.width - (getCssNum('--track-shell-width') || 0) - frontendLocalState.getScrollbarWidth()); }; @@ -143,9 +143,10 @@ class TraceViewer implements m.ClassComponent { onZoomed: (zoomedPositionPx: number, zoomRatio: number) => { // TODO(hjd): Avoid hardcoding TRACK_SHELL_WIDTH. // TODO(hjd): Improve support for zooming in overview timeline. - const zoomPx = zoomedPositionPx - TRACK_SHELL_WIDTH; + const trackShellWidth = (getCssNum('--track-shell-width') || 0); + const zoomPx = zoomedPositionPx - trackShellWidth; const rect = vnode.dom.getBoundingClientRect(); - const centerPoint = zoomPx / (rect.width - TRACK_SHELL_WIDTH); + const centerPoint = zoomPx / (rect.width - trackShellWidth); frontendLocalState.zoomVisibleWindow(1 - zoomRatio, centerPoint); globals.rafScheduler.scheduleRedraw(); }, @@ -162,6 +163,7 @@ class TraceViewer implements m.ClassComponent { const traceTime = globals.state.traceTime; const {visibleTimeScale} = frontendLocalState; this.keepCurrentSelection = true; + const trackShellWidth = (getCssNum('--track-shell-width') || 0); if (editing) { const selection = globals.state.currentSelection; if (selection !== null && selection.kind === 'AREA') { @@ -169,7 +171,7 @@ class TraceViewer implements m.ClassComponent { globals.frontendLocalState.selectedArea : globals.state.areas[selection.areaId]; const newTime = - visibleTimeScale.pxToHpTime(currentX - TRACK_SHELL_WIDTH) + visibleTimeScale.pxToHpTime(currentX - trackShellWidth) .toTPTime(); // Have to check again for when one boundary crosses over the other. const curBoundary = onTimeRangeBoundary(prevX); @@ -185,8 +187,8 @@ class TraceViewer implements m.ClassComponent { globals.state.areas[selection.areaId].tracks); } } else { - let startPx = Math.min(dragStartX, currentX) - TRACK_SHELL_WIDTH; - let endPx = Math.max(dragStartX, currentX) - TRACK_SHELL_WIDTH; + let startPx = Math.min(dragStartX, currentX) - trackShellWidth; + let endPx = Math.max(dragStartX, currentX) - trackShellWidth; if (startPx < 0 && endPx < 0) return; const {pxSpan} = visibleTimeScale; startPx = clamp(startPx, pxSpan.start, pxSpan.end); From 3d85dd4bc578de54d2dca8fcb9da8e064a7eecdb Mon Sep 17 00:00:00 2001 From: Andrew Levans Date: Tue, 7 May 2024 15:44:46 -0500 Subject: [PATCH 2/4] Resize on notes-panel --- ui/src/frontend/notes_panel.ts | 50 ++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/ui/src/frontend/notes_panel.ts b/ui/src/frontend/notes_panel.ts index 77624c706d..9cd7703181 100644 --- a/ui/src/frontend/notes_panel.ts +++ b/ui/src/frontend/notes_panel.ts @@ -74,6 +74,35 @@ export class NotesPanel extends Panel { }, {passive: true}); } + resize = (e: MouseEvent): void => { + e.stopPropagation(); + e.preventDefault(); + const mouseMoveEvent = (evMove: MouseEvent): void => { + evMove.preventDefault(); + const root = document.querySelector(':root'); + if (root && root instanceof HTMLElement && + 'layerX' in evMove && evMove.layerX && + typeof evMove.layerX === 'number' + ) { + if (evMove.layerX < 250) { + root.style.setProperty('--track-shell-width', '250px'); + } else { + root.style.setProperty('--track-shell-width', evMove.layerX + 'px'); + } + globals.rafScheduler.scheduleFullRedraw(); + } + }; + const mouseUpEvent = (evUp : MouseEvent): void => { + evUp.stopPropagation(); + evUp.preventDefault(); + document.removeEventListener('mousemove', mouseMoveEvent); + document.removeEventListener('mouseup', mouseUpEvent); + }; + document.addEventListener('mousemove', mouseMoveEvent); + document.addEventListener('mouseup', mouseUpEvent); + document.removeEventListener('mousedown', this.resize); + }; + view() { const allCollapsed = Object.values(globals.state.trackGroups) .every((group) => group.collapsed); @@ -85,6 +114,27 @@ export class NotesPanel extends Panel { this.onClick(e.layerX - (getCssNum('--track-shell-width') || 0), e.layerY); e.stopPropagation(); }, + onmousemove: (e: PerfettoMouseEvent)=>{ + if (e.currentTarget instanceof HTMLElement && + ( + (e.layerX +2) >= (getCssNum('--track-shell-width') || 0) && + (e.layerX -2) <= (getCssNum('--track-shell-width') || 0) + ) + ) { + document.addEventListener('mousedown', this.resize); + e.currentTarget.style.cursor = 'col-resize'; + return; + } else if (e.currentTarget instanceof HTMLElement) { + e.currentTarget.style.cursor = 'unset'; + } + document.removeEventListener('mousedown', this.resize); + }, + onmouseleave: (e: PerfettoMouseEvent) =>{ + if (e.currentTarget instanceof HTMLElement) { + e.currentTarget.style.cursor = 'unset'; + document.removeEventListener('mousedown', this.resize); + } + }, oncontextmenu: (e: PerfettoMouseEvent)=>{ this.onRightClick(e.layerX - (getCssNum('--track-shell-width') || 0), e.layerY); e.stopPropagation(); From e9a2e730362c79089d55955a4f30bb6e9f66a0f1 Mon Sep 17 00:00:00 2001 From: Andrew Levans Date: Tue, 7 May 2024 16:15:03 -0500 Subject: [PATCH 3/4] Resize on more parts of the vertical line --- ui/src/frontend/notes_panel.ts | 36 +++---------------------- ui/src/frontend/time_axis_panel.ts | 27 ++++++++++++++++++- ui/src/frontend/time_selection_panel.ts | 27 ++++++++++++++++++- ui/src/frontend/vertical_line_helper.ts | 30 +++++++++++++++++++++ 4 files changed, 86 insertions(+), 34 deletions(-) diff --git a/ui/src/frontend/notes_panel.ts b/ui/src/frontend/notes_panel.ts index 9cd7703181..88f3913a24 100644 --- a/ui/src/frontend/notes_panel.ts +++ b/ui/src/frontend/notes_panel.ts @@ -38,6 +38,7 @@ import { import {Panel, PanelSize} from './panel'; import {isTraceLoaded} from './sidebar'; import {customButtonRegistry} from './button_registry'; +import {resizeTrackShell} from './vertical_line_helper'; const FLAG_WIDTH = 16; const AREA_TRIANGLE_WIDTH = 10; @@ -74,35 +75,6 @@ export class NotesPanel extends Panel { }, {passive: true}); } - resize = (e: MouseEvent): void => { - e.stopPropagation(); - e.preventDefault(); - const mouseMoveEvent = (evMove: MouseEvent): void => { - evMove.preventDefault(); - const root = document.querySelector(':root'); - if (root && root instanceof HTMLElement && - 'layerX' in evMove && evMove.layerX && - typeof evMove.layerX === 'number' - ) { - if (evMove.layerX < 250) { - root.style.setProperty('--track-shell-width', '250px'); - } else { - root.style.setProperty('--track-shell-width', evMove.layerX + 'px'); - } - globals.rafScheduler.scheduleFullRedraw(); - } - }; - const mouseUpEvent = (evUp : MouseEvent): void => { - evUp.stopPropagation(); - evUp.preventDefault(); - document.removeEventListener('mousemove', mouseMoveEvent); - document.removeEventListener('mouseup', mouseUpEvent); - }; - document.addEventListener('mousemove', mouseMoveEvent); - document.addEventListener('mouseup', mouseUpEvent); - document.removeEventListener('mousedown', this.resize); - }; - view() { const allCollapsed = Object.values(globals.state.trackGroups) .every((group) => group.collapsed); @@ -121,18 +93,18 @@ export class NotesPanel extends Panel { (e.layerX -2) <= (getCssNum('--track-shell-width') || 0) ) ) { - document.addEventListener('mousedown', this.resize); + document.addEventListener('mousedown', resizeTrackShell); e.currentTarget.style.cursor = 'col-resize'; return; } else if (e.currentTarget instanceof HTMLElement) { e.currentTarget.style.cursor = 'unset'; } - document.removeEventListener('mousedown', this.resize); + document.removeEventListener('mousedown', resizeTrackShell); }, onmouseleave: (e: PerfettoMouseEvent) =>{ if (e.currentTarget instanceof HTMLElement) { e.currentTarget.style.cursor = 'unset'; - document.removeEventListener('mousedown', this.resize); + document.removeEventListener('mousedown', resizeTrackShell); } }, oncontextmenu: (e: PerfettoMouseEvent)=>{ diff --git a/ui/src/frontend/time_axis_panel.ts b/ui/src/frontend/time_axis_panel.ts index 306086f204..439159288a 100644 --- a/ui/src/frontend/time_axis_panel.ts +++ b/ui/src/frontend/time_axis_panel.ts @@ -28,10 +28,35 @@ import { timeScaleForVisibleWindow, } from './gridline_helper'; import {Panel, PanelSize} from './panel'; +import {PerfettoMouseEvent} from './events'; +import {resizeTrackShell} from './vertical_line_helper'; export class TimeAxisPanel extends Panel { view() { - return m('.time-axis-panel'); + return m('.time-axis-panel', { + + onmousemove: (e: PerfettoMouseEvent)=>{ + if (e.currentTarget instanceof HTMLElement && + ( + (e.layerX +2) >= (getCssNum('--track-shell-width') || 0) && + (e.layerX -2) <= (getCssNum('--track-shell-width') || 0) + ) + ) { + document.addEventListener('mousedown', resizeTrackShell); + e.currentTarget.style.cursor = 'col-resize'; + return; + } else if (e.currentTarget instanceof HTMLElement) { + e.currentTarget.style.cursor = 'unset'; + } + document.removeEventListener('mousedown', resizeTrackShell); + }, + onmouseleave: (e: PerfettoMouseEvent) =>{ + if (e.currentTarget instanceof HTMLElement) { + e.currentTarget.style.cursor = 'unset'; + document.removeEventListener('mousedown', resizeTrackShell); + } + }, + }); } renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) { diff --git a/ui/src/frontend/time_selection_panel.ts b/ui/src/frontend/time_selection_panel.ts index a79150b0ab..0e076c708f 100644 --- a/ui/src/frontend/time_selection_panel.ts +++ b/ui/src/frontend/time_selection_panel.ts @@ -33,6 +33,8 @@ import { timeScaleForVisibleWindow, } from './gridline_helper'; import {Panel, PanelSize} from './panel'; +import {PerfettoMouseEvent} from './events'; +import {resizeTrackShell} from './vertical_line_helper'; export interface BBox { x: number; @@ -128,7 +130,30 @@ function drawIBar( export class TimeSelectionPanel extends Panel { view() { - return m('.time-selection-panel'); + return m('.time-selection-panel', { + + onmousemove: (e: PerfettoMouseEvent)=>{ + if (e.currentTarget instanceof HTMLElement && + ( + (e.layerX +2) >= (getCssNum('--track-shell-width') || 0) && + (e.layerX -2) <= (getCssNum('--track-shell-width') || 0) + ) + ) { + document.addEventListener('mousedown', resizeTrackShell); + e.currentTarget.style.cursor = 'col-resize'; + return; + } else if (e.currentTarget instanceof HTMLElement) { + e.currentTarget.style.cursor = 'unset'; + } + document.removeEventListener('mousedown', resizeTrackShell); + }, + onmouseleave: (e: PerfettoMouseEvent) =>{ + if (e.currentTarget instanceof HTMLElement) { + e.currentTarget.style.cursor = 'unset'; + document.removeEventListener('mousedown', resizeTrackShell); + } + }, + }); } renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) { diff --git a/ui/src/frontend/vertical_line_helper.ts b/ui/src/frontend/vertical_line_helper.ts index 20bdb1b3e9..07c69fe599 100644 --- a/ui/src/frontend/vertical_line_helper.ts +++ b/ui/src/frontend/vertical_line_helper.ts @@ -14,6 +14,7 @@ import {TPTime} from '../common/time'; import {getCssNum} from './css_constants'; +import {globals} from './globals'; import {TimeScale} from './time_scale'; export function drawVerticalLineAtTime( @@ -27,6 +28,35 @@ export function drawVerticalLineAtTime( drawVerticalLine(ctx, xPos, height, color, lineWidth); } +export function resizeTrackShell(e: MouseEvent): void { + e.stopPropagation(); + e.preventDefault(); + const mouseMoveEvent = (evMove: MouseEvent): void => { + evMove.preventDefault(); + const root = document.querySelector(':root'); + if (root && root instanceof HTMLElement && + 'layerX' in evMove && evMove.layerX && + typeof evMove.layerX === 'number' + ) { + if (evMove.layerX < 250) { + root.style.setProperty('--track-shell-width', '250px'); + } else { + root.style.setProperty('--track-shell-width', evMove.layerX + 'px'); + } + globals.rafScheduler.scheduleFullRedraw(); + } + }; + const mouseUpEvent = (evUp : MouseEvent): void => { + evUp.stopPropagation(); + evUp.preventDefault(); + document.removeEventListener('mousemove', mouseMoveEvent); + document.removeEventListener('mouseup', mouseUpEvent); + }; + document.addEventListener('mousemove', mouseMoveEvent); + document.addEventListener('mouseup', mouseUpEvent); + document.removeEventListener('mousedown', resizeTrackShell); +}; + function drawVerticalLine(ctx: CanvasRenderingContext2D, xPos: number, height: number, From 48658c3b33b4c03a1fb5f04c1f6592e52840c12d Mon Sep 17 00:00:00 2001 From: Andrew Levans Date: Tue, 7 May 2024 16:39:33 -0500 Subject: [PATCH 4/4] Add an upper limit to track-shell-width --- ui/src/frontend/vertical_line_helper.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/src/frontend/vertical_line_helper.ts b/ui/src/frontend/vertical_line_helper.ts index 07c69fe599..387b955470 100644 --- a/ui/src/frontend/vertical_line_helper.ts +++ b/ui/src/frontend/vertical_line_helper.ts @@ -40,6 +40,10 @@ export function resizeTrackShell(e: MouseEvent): void { ) { if (evMove.layerX < 250) { root.style.setProperty('--track-shell-width', '250px'); + } else if (e.target && + e.target instanceof HTMLElement && + evMove.layerX > (e.target.clientWidth - 100)) { + root.style.setProperty('--track-shell-width', e.target.clientWidth-100 + 'px'); } else { root.style.setProperty('--track-shell-width', evMove.layerX + 'px'); }