blob: 431e0411eb93968c7ac181d7361354d519ff8815 [file] [log] [blame]
Isabelle Taylorec095152019-09-26 17:45:03 +01001// Copyright (C) 2019 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Isabelle Taylor613d38c2019-10-24 12:35:31 +010015import {Actions} from '../common/actions';
Isabelle Taylorec095152019-09-26 17:45:03 +010016import {getContainingTrackId} from '../common/state';
17import {fromNs, TimeSpan, toNs} from '../common/time';
18
19import {globals} from './globals';
20
21/**
22 * Given a timestamp, if |ts| is not currently in view move the view to
23 * center |ts|, keeping the same zoom level.
24 */
25export function horizontalScrollToTs(ts: number) {
26 const startNs = toNs(globals.frontendLocalState.visibleWindowTime.start);
27 const endNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
28 const currentViewNs = endNs - startNs;
29 if (ts < startNs || ts > endNs) {
30 // TODO(taylori): This is an ugly jump, we should do a smooth pan instead.
31 globals.frontendLocalState.updateVisibleTime(new TimeSpan(
32 fromNs(ts - currentViewNs / 2), fromNs(ts + currentViewNs / 2)));
33 }
34}
35
36/**
37 * Given a start and end timestamp (in ns), move the view to center this range
38 * and zoom to a level where the range is 1/5 of the viewport.
39 */
40export function horizontalScrollAndZoomToRange(startTs: number, endTs: number) {
41 const visibleDur = globals.frontendLocalState.visibleWindowTime.end -
42 globals.frontendLocalState.visibleWindowTime.start;
43 const selectDur = endTs - startTs;
44 const viewStartNs = toNs(globals.frontendLocalState.visibleWindowTime.start);
45 const viewEndNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
46 if (selectDur / visibleDur < 0.05 || startTs < viewStartNs ||
47 endTs > viewEndNs) {
48 globals.frontendLocalState.updateVisibleTime(
49 new TimeSpan(startTs - (selectDur * 2), endTs + (selectDur * 2)));
50 }
51}
52
53/**
54 * Given a track id, find a track with that id and scroll it into view. If the
55 * track is nested inside a track group, scroll to that track group instead.
Isabelle Taylor613d38c2019-10-24 12:35:31 +010056 * If |openGroup| then open the track group and scroll to the track.
Isabelle Taylorec095152019-09-26 17:45:03 +010057 */
Isabelle Taylor613d38c2019-10-24 12:35:31 +010058export function verticalScrollToTrack(
59 trackId: string|number, openGroup = false) {
Primiano Tuccic350da52019-11-01 12:13:01 +010060 const trackIdString = `${trackId}`;
Isabelle Taylor613d38c2019-10-24 12:35:31 +010061 const track = document.querySelector('#track_' + trackIdString);
Isabelle Taylorec095152019-09-26 17:45:03 +010062
Isabelle Taylor613d38c2019-10-24 12:35:31 +010063 if (track) {
64 // block: 'nearest' means that it will only scroll if the track is not
65 // currently in view.
66 track.scrollIntoView({behavior: 'smooth', block: 'nearest'});
67 return;
Isabelle Taylorec095152019-09-26 17:45:03 +010068 }
69
Isabelle Taylor613d38c2019-10-24 12:35:31 +010070 let trackGroup = null;
71 const trackGroupId = getContainingTrackId(globals.state, trackIdString);
72 if (trackGroupId) {
73 trackGroup = document.querySelector('#track_' + trackGroupId);
74 }
75
76 if (!trackGroupId || !trackGroup) {
Isabelle Taylorec095152019-09-26 17:45:03 +010077 console.error(`Can't scroll, track (${trackIdString}) not found.`);
78 return;
79 }
80
Isabelle Taylor613d38c2019-10-24 12:35:31 +010081 // The requested track is inside a closed track group, either open the track
82 // group and scroll to the track or just scroll to the track group.
83 if (openGroup) {
84 // After the track exists in the dom, it will be scrolled to.
85 globals.frontendLocalState.scrollToTrackId = trackId;
86 globals.dispatch(Actions.toggleTrackGroupCollapsed({trackGroupId}));
87 return;
88 } else {
89 trackGroup.scrollIntoView({behavior: 'smooth', block: 'nearest'});
90 }
Isabelle Taylorec095152019-09-26 17:45:03 +010091}
92
Isabelle Taylor613d38c2019-10-24 12:35:31 +010093
Isabelle Taylorec095152019-09-26 17:45:03 +010094/**
95 * Scroll vertically and horizontally to reach track (|trackId|) at |ts|.
96 */
Isabelle Taylor613d38c2019-10-24 12:35:31 +010097export function scrollToTrackAndTs(
Primiano Tuccic350da52019-11-01 12:13:01 +010098 trackId: string|number|undefined, ts: number, openGroup = false) {
99 if (trackId !== undefined) {
100 verticalScrollToTrack(trackId, openGroup);
101 }
Isabelle Taylorec095152019-09-26 17:45:03 +0100102 horizontalScrollToTs(ts);
103}