1/*
2 * Copyright 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import {FixedStringFormatter} from 'trace/tree_node/formatters';
18import {Operation} from 'trace/tree_node/operations/operation';
19import {UiPropertyTreeNode} from 'viewers/common/ui_property_tree_node';
20
21export class DispatchEntryFormatter implements Operation<UiPropertyTreeNode> {
22  static readonly AXIS_X = 0;
23  static readonly AXIS_Y = 1;
24
25  constructor(private readonly layerIdToName: Map<number, string>) {}
26
27  apply(node: UiPropertyTreeNode): void {
28    node.getAllChildren().forEach((dispatchEntry) => {
29      this.formatTargetWindow(dispatchEntry);
30      this.formatDispatchedPointers(dispatchEntry);
31    });
32  }
33
34  private formatTargetWindow(dispatchEntry: UiPropertyTreeNode) {
35    const windowIdNode = dispatchEntry.getChildByName('windowId');
36    if (windowIdNode === undefined) {
37      return;
38    }
39    windowIdNode.setDisplayName('TargetWindow');
40    const windowId = Number(windowIdNode.getValue() ?? -1);
41    const layerName = this.layerIdToName.get(windowId);
42    windowIdNode.setFormatter(
43      new FixedStringFormatter(
44        `${windowId} - ${layerName ?? '<Unknown Name>'}`,
45      ),
46    );
47  }
48
49  private formatDispatchedPointers(dispatchEntry: UiPropertyTreeNode) {
50    const dispatchedPointerNode =
51      dispatchEntry.getChildByName('dispatchedPointer');
52    if (dispatchedPointerNode === undefined) {
53      return;
54    }
55    dispatchedPointerNode.setDisplayName('DispatchedPointersInWindowSpace');
56    let formattedPointers = '';
57    dispatchedPointerNode.getAllChildren()?.forEach((pointer) => {
58      const axisValues = pointer.getChildByName('axisValueInWindow');
59      let x = '?';
60      let y = '?';
61      axisValues?.getAllChildren()?.forEach((axisValue) => {
62        const axis = Number(axisValue.getChildByName('axis')?.getValue());
63        if (axis === DispatchEntryFormatter.AXIS_X) {
64          x = axisValue.getChildByName('value')?.getValue() ?? '?';
65          return;
66        }
67        if (axis === DispatchEntryFormatter.AXIS_Y) {
68          y = axisValue.getChildByName('value')?.getValue() ?? '?';
69          return;
70        }
71      });
72      if (formattedPointers.length > 0) {
73        formattedPointers += ', ';
74      }
75      formattedPointers += `(${x}, ${y})`;
76    });
77    if (formattedPointers.length === 0) {
78      formattedPointers = '<none>';
79    }
80    dispatchedPointerNode.setFormatter(
81      new FixedStringFormatter(formattedPointers),
82    );
83  }
84}
85