Skip to content

Commit fea5bb7

Browse files
Make pinned tracks scrollable (#135)
* Make pinned tracks scrollable * Add Resize logic to the pinned track section
1 parent fe7f68f commit fea5bb7

File tree

5 files changed

+82
-6
lines changed

5 files changed

+82
-6
lines changed

ui/src/assets/common.scss

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,6 @@ $bottom-tab-padding: 10px;
470470
overflow-x: hidden;
471471
overflow-y: auto;
472472
flex: 1 1 auto;
473-
will-change: transform; // Force layer creation.
474473
display: grid;
475474
grid-template-columns: 1fr;
476475
grid-template-rows: 1fr;
@@ -492,7 +491,7 @@ $bottom-tab-padding: 10px;
492491
grid-template-areas: "space";
493492
}
494493

495-
.pinned-panel-container {
494+
.overview-panel-container {
496495
position: relative;
497496
// Override top level overflow: hidden so height of this flex item can be
498497
// its content height.
@@ -525,7 +524,7 @@ canvas.main-canvas {
525524
user-select: none;
526525
}
527526

528-
.scrolling-panel-container > .panels > *:last-child {
527+
.scrolling-panel-container:not(.pinned-group) > .panels > *:last-child {
529528
margin-bottom: 500px;
530529
}
531530

ui/src/common/actions.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,6 +1558,12 @@ export const StateActions = {
15581558
_: {}) {
15591559
state.pinnedGroupCollapsed = !state.pinnedGroupCollapsed;
15601560
},
1561+
1562+
setPinnedPanelHeight(
1563+
state: StateDraft,
1564+
args: {newHeight: number}) {
1565+
state.pinnedPanelHeight = args.newHeight;
1566+
},
15611567
clearTrackAndGroupSelection(
15621568
state: StateDraft,
15631569
_: {},

ui/src/common/empty_state.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ export function createEmptyState(): State {
172172

173173
filteredTracks: [],
174174
pinnedGroupCollapsed: false,
175+
pinnedPanelHeight: 400,
175176
selectedTrackGroupIds: new Set<string>(),
176177
selectedTrackIds: new Set<string>(),
177178
};

ui/src/common/state.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ export interface State {
580580
visualisedArgs: string[];
581581
filteredTracks: AddTrackLikeArgs[];
582582
pinnedGroupCollapsed: boolean;
583+
pinnedPanelHeight: number;
583584

584585
/**
585586
* This state is updated on the frontend at 60Hz and eventually syncronised to

ui/src/frontend/viewer_page.ts

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,57 @@ class TraceViewer implements m.ClassComponent<TraceViewerAttrs> {
233233
window.removeEventListener('resize', this.onResize);
234234
if (this.zoomContent) this.zoomContent.shutdown();
235235
}
236+
pinnedTrackResize = (e: MouseEvent)=>{
237+
e.stopPropagation();
238+
e.preventDefault();
239+
if (e.currentTarget instanceof HTMLElement) {
240+
const timelineElement = e.currentTarget.closest('div.pan-and-zoom-content');
241+
if (timelineElement && timelineElement instanceof HTMLDivElement) {
242+
let mouseY = e.clientY;
243+
const mouseMoveEvent = (evMove: MouseEvent): void => {
244+
evMove.preventDefault();
245+
const movementY = evMove.clientY-mouseY;
246+
globals.dispatch(
247+
Actions.setPinnedPanelHeight(
248+
{newHeight: globals.state.pinnedPanelHeight + movementY}));
249+
mouseY = evMove.clientY;
236250

251+
globals.rafScheduler.scheduleFullRedraw();
252+
};
253+
const mouseReturnEvent = () : void => {
254+
timelineElement.addEventListener('mousemove', mouseMoveEvent);
255+
timelineElement.removeEventListener('mouseenter', mouseReturnEvent);
256+
};
257+
const mouseLeaveEvent = () : void => {
258+
timelineElement.removeEventListener('mousemove', mouseMoveEvent);
259+
timelineElement.addEventListener('mouseenter', mouseReturnEvent);
260+
};
261+
const mouseUpEvent = (): void => {
262+
timelineElement.removeEventListener('mousemove', mouseMoveEvent);
263+
document.removeEventListener('mouseup', mouseUpEvent);
264+
timelineElement.removeEventListener('mouseenter', mouseReturnEvent);
265+
timelineElement.removeEventListener('mouseleave', mouseLeaveEvent);
266+
};
267+
timelineElement.addEventListener('mousemove', mouseMoveEvent);
268+
timelineElement.addEventListener('mouseleave', mouseLeaveEvent);
269+
document.addEventListener('mouseup', mouseUpEvent);
270+
}
271+
}
272+
};
273+
checkPinnedResize = (e: MouseEvent) =>{
274+
if (e.currentTarget instanceof HTMLElement &&
275+
e.type !== 'mouseleave'
276+
) {
277+
const timelineElement: HTMLDivElement | null = e.currentTarget.closest('div.pan-and-zoom-content');
278+
timelineElement?.addEventListener('mousedown', this.pinnedTrackResize);
279+
e.currentTarget.style.cursor = 'row-resize';
280+
return;
281+
} else if (e.currentTarget instanceof HTMLElement) {
282+
const timelineElement: HTMLDivElement | null = e.currentTarget.closest('div.pan-and-zoom-content');
283+
timelineElement?.removeEventListener('mousedown', this.pinnedTrackResize);
284+
e.currentTarget.style.cursor = 'unset';
285+
}
286+
};
237287
view() {
238288
const rootNode: AnyAttrsVnode[] = [];
239289
const renderGroup = (group: TrackGroupState, panels: AnyAttrsVnode[]) => {
@@ -290,13 +340,14 @@ class TraceViewer implements m.ClassComponent<TraceViewerAttrs> {
290340
if (OVERVIEW_PANEL_FLAG.get()) {
291341
overviewPanel.push(m(OverviewTimelinePanel, {key: 'overview'}));
292342
}
293-
const pinnedPanels: AnyAttrsVnode[] = [
343+
const overviewPanels: AnyAttrsVnode[] = [
294344
...overviewPanel,
295345
m(TimeAxisPanel, {key: 'timeaxis'}),
296346
m(TimeSelectionPanel, {key: 'timeselection'}),
297347
m(NotesPanel, {key: 'notes'}),
298348
m(TickmarkPanel, {key: 'searchTickmarks'}),
299349
];
350+
const pinnedPanels: AnyAttrsVnode[] = [];
300351
if (globals.state.pinnedTracks.length > 0) {
301352
pinnedPanels.push(m(TrackGroup, {
302353
header: m(MinimalTrackGroup, {
@@ -314,6 +365,7 @@ class TraceViewer implements m.ClassComponent<TraceViewerAttrs> {
314365
} as TrackGroupAttrs));
315366
}
316367

368+
317369
return m(
318370
'.page',
319371
m('.split-panel',
@@ -328,11 +380,28 @@ class TraceViewer implements m.ClassComponent<TraceViewerAttrs> {
328380
globals.makeSelection(Actions.deselect({}));
329381
},
330382
},
331-
m('.pinned-panel-container', m(PanelContainer, {
383+
m('.overview-panel-container', m(PanelContainer, {
332384
doesScroll: false,
333-
panels: pinnedPanels,
385+
panels: overviewPanels,
334386
kind: 'OVERVIEW',
335387
})),
388+
m('.scrolling-panel-container pinned-group', {style: {
389+
minHeight: !globals.state.pinnedGroupCollapsed?globals.state.pinnedPanelHeight+ 'px': '18px',
390+
height: !globals.state.pinnedGroupCollapsed?globals.state.pinnedPanelHeight+ 'px': '18px',
391+
}}, m(PanelContainer, {
392+
doesScroll: true,
393+
panels: pinnedPanels,
394+
kind: 'TRACKS',
395+
})),
396+
m('hr', {
397+
style: {
398+
width: '100%',
399+
margin: '0',
400+
cursor: 'row-resize',
401+
},
402+
onmousemove: this.checkPinnedResize,
403+
onmouseleave: this.checkPinnedResize,
404+
}),
336405
m('.scrolling-panel-container', m(PanelContainer, {
337406
doesScroll: true,
338407
panels: rootNode,

0 commit comments

Comments
 (0)