• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2024 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 {assertUnreachable} from '../base/logging';
17import {Icons} from '../base/semantic_icons';
18import {Timestamp} from '../components/widgets/timestamp';
19import {TraceImpl} from '../core/trace_impl';
20import {Note, SpanNote} from '../public/note';
21import {NoteSelection} from '../public/selection';
22import {Button} from '../widgets/button';
23
24function getStartTimestamp(note: Note | SpanNote) {
25  const noteType = note.noteType;
26  switch (noteType) {
27    case 'SPAN':
28      return note.start;
29    case 'DEFAULT':
30      return note.timestamp;
31    default:
32      assertUnreachable(noteType);
33  }
34}
35
36interface NodeDetailsPanelAttrs {
37  readonly trace: TraceImpl;
38  readonly selection: NoteSelection;
39}
40
41export class NoteEditor implements m.ClassComponent<NodeDetailsPanelAttrs> {
42  view(vnode: m.CVnode<NodeDetailsPanelAttrs>) {
43    const {selection, trace} = vnode.attrs;
44    const id = selection.id;
45    const note = trace.notes.getNote(id);
46    if (note === undefined) {
47      return m('.', `No Note with id ${id}`);
48    }
49    const startTime = getStartTimestamp(note);
50    return m(
51      '.notes-editor-panel',
52      {
53        key: id, // Every note shoul get its own brand new DOM.
54      },
55      m(
56        '.notes-editor-panel-heading-bar',
57        m(
58          '.notes-editor-panel-heading',
59          `Annotation at `,
60          m(Timestamp, {ts: startTime}),
61        ),
62        m('input[type=text]', {
63          oncreate: (v: m.VnodeDOM) => {
64            // NOTE: due to bad design decisions elsewhere this component is
65            // rendered every time the mouse moves on the canvas. We cannot set
66            // `value: note.text` as an input as that will clobber the input
67            // value as we move the mouse.
68            const inputElement = v.dom as HTMLInputElement;
69            inputElement.value = note.text;
70          },
71          onchange: (e: InputEvent) => {
72            const newText = (e.target as HTMLInputElement).value;
73            trace.notes.changeNote(id, {text: newText});
74          },
75        }),
76        m(
77          'span.color-change',
78          `Change color: `,
79          m('input[type=color]', {
80            value: note.color,
81            onchange: (e: Event) => {
82              const newColor = (e.target as HTMLInputElement).value;
83              trace.notes.changeNote(id, {color: newColor});
84            },
85          }),
86        ),
87        m(Button, {
88          label: 'Remove',
89          icon: Icons.Delete,
90          onclick: () => trace.notes.removeNote(id),
91        }),
92      ),
93    );
94  }
95}
96