• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// 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 size 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 * as m from 'mithril';
16
17import {timeToString} from '../common/time';
18import {TimeSpan} from '../common/time';
19
20import {globals} from './globals';
21import {gridlines} from './gridline_helper';
22import {Panel, PanelSize} from './panel';
23import {TRACK_SHELL_WIDTH} from './track_constants';
24
25export interface BBox {
26  x: number;
27  y: number;
28  width: number;
29  height: number;
30}
31
32// Draws a vertical line with two horizontal tails at the left and right and
33// a label in the middle. It looks a bit like a stretched H:
34// |--- Label ---|
35// The |target| bounding box determines where to draw the H.
36// The |bounds| bounding box gives the visible region, this is used to adjust
37// the positioning of the label to ensure it is on screen.
38function drawHBar(
39    ctx: CanvasRenderingContext2D, target: BBox, bounds: BBox, label: string) {
40  ctx.fillStyle = '#222';
41
42  const xLeft = Math.floor(target.x);
43  const xRight = Math.ceil(target.x + target.width);
44  const yMid = Math.floor(target.height / 2 + target.y);
45  const xWidth = xRight - xLeft;
46
47  // Draw horizontal bar of the H.
48  ctx.fillRect(xLeft, yMid, xWidth, 1);
49  // Draw left vertical bar of the H.
50  ctx.fillRect(xLeft, target.y, 1, target.height);
51  // Draw right vertical bar of the H.
52  ctx.fillRect(xRight, target.y, 1, target.height);
53
54  const labelWidth = ctx.measureText(label).width;
55
56  // Find a good position for the label:
57  // By default put the label in the middle of the H:
58  let labelXLeft = Math.floor(xWidth / 2 - labelWidth / 2 + xLeft);
59
60  if (labelWidth > target.width || labelXLeft < bounds.x ||
61      (labelXLeft + labelWidth) > (bounds.x + bounds.width)) {
62    // It won't fit in the middle or would be at least partly out of bounds
63    // so put it either to the left or right:
64    if (xRight > bounds.x + bounds.width) {
65      // If the H extends off the right side of the screen the label
66      // goes on the left of the H.
67      labelXLeft = xLeft - labelWidth - 3;
68    } else {
69      // Otherwise the label goes on the right of the H.
70      labelXLeft = xRight + 3;
71    }
72  }
73
74  ctx.fillStyle = '#ffffff';
75  ctx.fillRect(labelXLeft - 1, 0, labelWidth + 1, target.height);
76
77  ctx.textBaseline = 'middle';
78  ctx.fillStyle = '#222';
79  ctx.font = '10px Google Sans';
80  ctx.fillText(label, labelXLeft, yMid);
81}
82
83export class TimeSelectionPanel extends Panel {
84  view() {
85    return m('.time-selection-panel');
86  }
87
88  renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
89    const range = globals.frontendLocalState.visibleWindowTime;
90    const timeScale = globals.frontendLocalState.timeScale;
91
92    ctx.fillStyle = '#999';
93    ctx.fillRect(TRACK_SHELL_WIDTH - 1, 0, 2, size.height);
94    for (const xAndTime of gridlines(size.width, range, timeScale)) {
95      ctx.fillRect(xAndTime[0], 0, 1, size.height);
96    }
97
98    const selection = globals.state.currentSelection;
99    if (selection !== null && selection.kind === `TIMESPAN`) {
100      const start = Math.min(selection.startTs, selection.endTs);
101      const end = Math.max(selection.startTs, selection.endTs);
102      this.renderSpan(ctx, size, new TimeSpan(start, end));
103    }
104  }
105
106  renderSpan(ctx: CanvasRenderingContext2D, size: PanelSize, span: TimeSpan) {
107    const timeScale = globals.frontendLocalState.timeScale;
108    const xLeft = timeScale.timeToPx(span.start);
109    const xRight = timeScale.timeToPx(span.end);
110    const label = timeToString(span.duration);
111    drawHBar(
112        ctx,
113        {
114          x: TRACK_SHELL_WIDTH + xLeft,
115          y: 0,
116          width: xRight - xLeft,
117          height: size.height
118        },
119        {x: 0, y: 0, width: size.width, height: size.height},
120        label);
121  }
122}
123