xref: /aosp_15_r20/external/perfetto/ui/src/components/widgets/timestamp.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1// Copyright (C) 2023 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 m from 'mithril';
16import {copyToClipboard} from '../../base/clipboard';
17import {assertExists} from '../../base/logging';
18import {Icons} from '../../base/semantic_icons';
19import {time, Time} from '../../base/time';
20import {AppImpl} from '../../core/app_impl';
21import {Anchor} from '../../widgets/anchor';
22import {MenuDivider, MenuItem, PopupMenu2} from '../../widgets/menu';
23import {Trace} from '../../public/trace';
24import {TimestampFormatMenuItem} from './timestamp_format_menu';
25import {renderTimecode} from '../time_utils';
26import {TimestampFormat} from '../../public/timeline';
27
28// import {MenuItem, PopupMenu2} from './menu';
29
30interface TimestampAttrs {
31  // The timestamp to print, this should be the absolute, raw timestamp as
32  // found in trace processor.
33  ts: time;
34  // Custom text value to show instead of the default HH:MM:SS.mmm uuu nnn
35  // formatting.
36  display?: m.Children;
37  extraMenuItems?: m.Child[];
38}
39
40export class Timestamp implements m.ClassComponent<TimestampAttrs> {
41  private readonly trace: Trace;
42
43  constructor() {
44    // TODO(primiano): the Trace object should be injected into the attrs, but
45    // there are too many users of this class and doing so requires a larger
46    // refactoring CL. Either that or we should find a different way to plumb
47    // the hoverCursorTimestamp.
48    this.trace = assertExists(AppImpl.instance.trace);
49  }
50
51  view({attrs}: m.Vnode<TimestampAttrs>) {
52    const {ts} = attrs;
53    const timeline = this.trace.timeline;
54    return m(
55      PopupMenu2,
56      {
57        trigger: m(
58          Anchor,
59          {
60            onmouseover: () => (timeline.hoverCursorTimestamp = ts),
61            onmouseout: () => (timeline.hoverCursorTimestamp = undefined),
62          },
63          attrs.display ?? this.formatTimestamp(timeline.toDomainTime(ts)),
64        ),
65      },
66      m(MenuItem, {
67        icon: Icons.Copy,
68        label: `Copy raw value`,
69        onclick: () => {
70          copyToClipboard(ts.toString());
71        },
72      }),
73      m(TimestampFormatMenuItem, {trace: this.trace}),
74      attrs.extraMenuItems ? [m(MenuDivider), attrs.extraMenuItems] : null,
75    );
76  }
77
78  private formatTimestamp(time: time): m.Children {
79    const fmt = this.trace.timeline.timestampFormat;
80    switch (fmt) {
81      case TimestampFormat.UTC:
82      case TimestampFormat.TraceTz:
83      case TimestampFormat.Timecode:
84        return renderTimecode(time);
85      case TimestampFormat.TraceNs:
86        return time.toString();
87      case TimestampFormat.TraceNsLocale:
88        return time.toLocaleString();
89      case TimestampFormat.Seconds:
90        return Time.formatSeconds(time);
91      case TimestampFormat.Milliseconds:
92        return Time.formatMilliseconds(time);
93      case TimestampFormat.Microseconds:
94        return Time.formatMicroseconds(time);
95      default:
96        const x: never = fmt;
97        throw new Error(`Invalid timestamp ${x}`);
98    }
99  }
100}
101