xref: /aosp_15_r20/external/perfetto/ui/src/components/widgets/timestamp.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker// Copyright (C) 2023 The Android Open Source Project
2*6dbdd20aSAndroid Build Coastguard Worker//
3*6dbdd20aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*6dbdd20aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*6dbdd20aSAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*6dbdd20aSAndroid Build Coastguard Worker//
7*6dbdd20aSAndroid Build Coastguard Worker//      http://www.apache.org/licenses/LICENSE-2.0
8*6dbdd20aSAndroid Build Coastguard Worker//
9*6dbdd20aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*6dbdd20aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*6dbdd20aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*6dbdd20aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*6dbdd20aSAndroid Build Coastguard Worker// limitations under the License.
14*6dbdd20aSAndroid Build Coastguard Worker
15*6dbdd20aSAndroid Build Coastguard Workerimport m from 'mithril';
16*6dbdd20aSAndroid Build Coastguard Workerimport {copyToClipboard} from '../../base/clipboard';
17*6dbdd20aSAndroid Build Coastguard Workerimport {assertExists} from '../../base/logging';
18*6dbdd20aSAndroid Build Coastguard Workerimport {Icons} from '../../base/semantic_icons';
19*6dbdd20aSAndroid Build Coastguard Workerimport {time, Time} from '../../base/time';
20*6dbdd20aSAndroid Build Coastguard Workerimport {AppImpl} from '../../core/app_impl';
21*6dbdd20aSAndroid Build Coastguard Workerimport {Anchor} from '../../widgets/anchor';
22*6dbdd20aSAndroid Build Coastguard Workerimport {MenuDivider, MenuItem, PopupMenu2} from '../../widgets/menu';
23*6dbdd20aSAndroid Build Coastguard Workerimport {Trace} from '../../public/trace';
24*6dbdd20aSAndroid Build Coastguard Workerimport {TimestampFormatMenuItem} from './timestamp_format_menu';
25*6dbdd20aSAndroid Build Coastguard Workerimport {renderTimecode} from '../time_utils';
26*6dbdd20aSAndroid Build Coastguard Workerimport {TimestampFormat} from '../../public/timeline';
27*6dbdd20aSAndroid Build Coastguard Worker
28*6dbdd20aSAndroid Build Coastguard Worker// import {MenuItem, PopupMenu2} from './menu';
29*6dbdd20aSAndroid Build Coastguard Worker
30*6dbdd20aSAndroid Build Coastguard Workerinterface TimestampAttrs {
31*6dbdd20aSAndroid Build Coastguard Worker  // The timestamp to print, this should be the absolute, raw timestamp as
32*6dbdd20aSAndroid Build Coastguard Worker  // found in trace processor.
33*6dbdd20aSAndroid Build Coastguard Worker  ts: time;
34*6dbdd20aSAndroid Build Coastguard Worker  // Custom text value to show instead of the default HH:MM:SS.mmm uuu nnn
35*6dbdd20aSAndroid Build Coastguard Worker  // formatting.
36*6dbdd20aSAndroid Build Coastguard Worker  display?: m.Children;
37*6dbdd20aSAndroid Build Coastguard Worker  extraMenuItems?: m.Child[];
38*6dbdd20aSAndroid Build Coastguard Worker}
39*6dbdd20aSAndroid Build Coastguard Worker
40*6dbdd20aSAndroid Build Coastguard Workerexport class Timestamp implements m.ClassComponent<TimestampAttrs> {
41*6dbdd20aSAndroid Build Coastguard Worker  private readonly trace: Trace;
42*6dbdd20aSAndroid Build Coastguard Worker
43*6dbdd20aSAndroid Build Coastguard Worker  constructor() {
44*6dbdd20aSAndroid Build Coastguard Worker    // TODO(primiano): the Trace object should be injected into the attrs, but
45*6dbdd20aSAndroid Build Coastguard Worker    // there are too many users of this class and doing so requires a larger
46*6dbdd20aSAndroid Build Coastguard Worker    // refactoring CL. Either that or we should find a different way to plumb
47*6dbdd20aSAndroid Build Coastguard Worker    // the hoverCursorTimestamp.
48*6dbdd20aSAndroid Build Coastguard Worker    this.trace = assertExists(AppImpl.instance.trace);
49*6dbdd20aSAndroid Build Coastguard Worker  }
50*6dbdd20aSAndroid Build Coastguard Worker
51*6dbdd20aSAndroid Build Coastguard Worker  view({attrs}: m.Vnode<TimestampAttrs>) {
52*6dbdd20aSAndroid Build Coastguard Worker    const {ts} = attrs;
53*6dbdd20aSAndroid Build Coastguard Worker    const timeline = this.trace.timeline;
54*6dbdd20aSAndroid Build Coastguard Worker    return m(
55*6dbdd20aSAndroid Build Coastguard Worker      PopupMenu2,
56*6dbdd20aSAndroid Build Coastguard Worker      {
57*6dbdd20aSAndroid Build Coastguard Worker        trigger: m(
58*6dbdd20aSAndroid Build Coastguard Worker          Anchor,
59*6dbdd20aSAndroid Build Coastguard Worker          {
60*6dbdd20aSAndroid Build Coastguard Worker            onmouseover: () => (timeline.hoverCursorTimestamp = ts),
61*6dbdd20aSAndroid Build Coastguard Worker            onmouseout: () => (timeline.hoverCursorTimestamp = undefined),
62*6dbdd20aSAndroid Build Coastguard Worker          },
63*6dbdd20aSAndroid Build Coastguard Worker          attrs.display ?? this.formatTimestamp(timeline.toDomainTime(ts)),
64*6dbdd20aSAndroid Build Coastguard Worker        ),
65*6dbdd20aSAndroid Build Coastguard Worker      },
66*6dbdd20aSAndroid Build Coastguard Worker      m(MenuItem, {
67*6dbdd20aSAndroid Build Coastguard Worker        icon: Icons.Copy,
68*6dbdd20aSAndroid Build Coastguard Worker        label: `Copy raw value`,
69*6dbdd20aSAndroid Build Coastguard Worker        onclick: () => {
70*6dbdd20aSAndroid Build Coastguard Worker          copyToClipboard(ts.toString());
71*6dbdd20aSAndroid Build Coastguard Worker        },
72*6dbdd20aSAndroid Build Coastguard Worker      }),
73*6dbdd20aSAndroid Build Coastguard Worker      m(TimestampFormatMenuItem, {trace: this.trace}),
74*6dbdd20aSAndroid Build Coastguard Worker      attrs.extraMenuItems ? [m(MenuDivider), attrs.extraMenuItems] : null,
75*6dbdd20aSAndroid Build Coastguard Worker    );
76*6dbdd20aSAndroid Build Coastguard Worker  }
77*6dbdd20aSAndroid Build Coastguard Worker
78*6dbdd20aSAndroid Build Coastguard Worker  private formatTimestamp(time: time): m.Children {
79*6dbdd20aSAndroid Build Coastguard Worker    const fmt = this.trace.timeline.timestampFormat;
80*6dbdd20aSAndroid Build Coastguard Worker    switch (fmt) {
81*6dbdd20aSAndroid Build Coastguard Worker      case TimestampFormat.UTC:
82*6dbdd20aSAndroid Build Coastguard Worker      case TimestampFormat.TraceTz:
83*6dbdd20aSAndroid Build Coastguard Worker      case TimestampFormat.Timecode:
84*6dbdd20aSAndroid Build Coastguard Worker        return renderTimecode(time);
85*6dbdd20aSAndroid Build Coastguard Worker      case TimestampFormat.TraceNs:
86*6dbdd20aSAndroid Build Coastguard Worker        return time.toString();
87*6dbdd20aSAndroid Build Coastguard Worker      case TimestampFormat.TraceNsLocale:
88*6dbdd20aSAndroid Build Coastguard Worker        return time.toLocaleString();
89*6dbdd20aSAndroid Build Coastguard Worker      case TimestampFormat.Seconds:
90*6dbdd20aSAndroid Build Coastguard Worker        return Time.formatSeconds(time);
91*6dbdd20aSAndroid Build Coastguard Worker      case TimestampFormat.Milliseconds:
92*6dbdd20aSAndroid Build Coastguard Worker        return Time.formatMilliseconds(time);
93*6dbdd20aSAndroid Build Coastguard Worker      case TimestampFormat.Microseconds:
94*6dbdd20aSAndroid Build Coastguard Worker        return Time.formatMicroseconds(time);
95*6dbdd20aSAndroid Build Coastguard Worker      default:
96*6dbdd20aSAndroid Build Coastguard Worker        const x: never = fmt;
97*6dbdd20aSAndroid Build Coastguard Worker        throw new Error(`Invalid timestamp ${x}`);
98*6dbdd20aSAndroid Build Coastguard Worker    }
99*6dbdd20aSAndroid Build Coastguard Worker  }
100*6dbdd20aSAndroid Build Coastguard Worker}
101