• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2018 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
15import {TimeSpan} from '../common/time';
16
17const MAX_ZOOM_SPAN_SEC = 1e-4;  // 0.1 ms.
18
19/**
20 * Defines a mapping between number and seconds for the entire application.
21 * Linearly scales time values from boundsMs to pixel values in boundsPx and
22 * back.
23 */
24export class TimeScale {
25  private timeBounds: TimeSpan;
26  private _startPx: number;
27  private _endPx: number;
28  private secPerPx = 0;
29
30  constructor(timeBounds: TimeSpan, boundsPx: [number, number]) {
31    this.timeBounds = timeBounds;
32    this._startPx = boundsPx[0];
33    this._endPx = boundsPx[1];
34    this.updateSlope();
35  }
36
37  private updateSlope() {
38    this.secPerPx = this.timeBounds.duration / (this._endPx - this._startPx);
39  }
40
41  deltaTimeToPx(time: number): number {
42    return Math.round(time / this.secPerPx);
43  }
44
45  timeToPx(time: number): number {
46    return this._startPx + (time - this.timeBounds.start) / this.secPerPx;
47  }
48
49  pxToTime(px: number): number {
50    return this.timeBounds.start + (px - this._startPx) * this.secPerPx;
51  }
52
53  deltaPxToDuration(px: number): number {
54    return px * this.secPerPx;
55  }
56
57  setTimeBounds(timeBounds: TimeSpan) {
58    this.timeBounds = timeBounds;
59    this.updateSlope();
60  }
61
62  setLimitsPx(pxStart: number, pxEnd: number) {
63    this._startPx = pxStart;
64    this._endPx = pxEnd;
65    this.updateSlope();
66  }
67
68  timeInBounds(time: number): boolean {
69    return this.timeBounds.isInBounds(time);
70  }
71
72  get startPx(): number {
73    return this._startPx;
74  }
75
76  get endPx(): number {
77    return this._endPx;
78  }
79}
80
81export function computeZoom(
82    scale: TimeScale, span: TimeSpan, zoomFactor: number, zoomPx: number):
83    TimeSpan {
84  const startPx = scale.startPx;
85  const endPx = scale.endPx;
86  const deltaPx = endPx - startPx;
87  const deltaTime = span.end - span.start;
88  const newDeltaTime = Math.max(deltaTime * zoomFactor, MAX_ZOOM_SPAN_SEC);
89  const clampedZoomPx = Math.max(startPx, Math.min(endPx, zoomPx));
90  const zoomTime = scale.pxToTime(clampedZoomPx);
91  const r = (clampedZoomPx - startPx) / deltaPx;
92  const newStartTime = zoomTime - newDeltaTime * r;
93  const newEndTime = newStartTime + newDeltaTime;
94  return new TimeSpan(newStartTime, newEndTime);
95}
96