• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 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 */
16import {
17  Component,
18  ElementRef,
19  EventEmitter,
20  Inject,
21  Input,
22  Output,
23} from '@angular/core';
24import {assertDefined} from 'common/assert_utils';
25import {SfCuratedProperties} from 'viewers/common/curated_properties';
26import {UiPropertyTreeNode} from 'viewers/common/ui_property_tree_node';
27import {ViewerEvents} from 'viewers/common/viewer_events';
28import {inlineButtonStyle} from './styles/clickable_property.styles';
29import {viewerCardInnerStyle} from './styles/viewer_card.styles';
30
31@Component({
32  selector: 'surface-flinger-property-groups',
33  template: `
34    <div class="title-section">
35      <collapsible-section-title
36        title="PROPERTIES"
37        (collapseButtonClicked)="collapseButtonClicked.emit()"></collapsible-section-title>
38    </div>
39
40    <span class="mat-body-1 placeholder-text" *ngIf="!properties"> Layer not selected. </span>
41
42    <div class="property-groups-content" *ngIf="properties">
43      <div class="group">
44        <h3 class="group-header mat-subheading-2">Visibility</h3>
45        <div class="left-column">
46          <p class="mat-body-2 flags">
47            <span class="mat-body-1">Flags:</span>
48            &ngsp;
49            {{ properties.flags }}
50          </p>
51          <span *ngFor="let summaryProperty of properties.summary" class="mat-body-2 summary inline">
52            <span class="mat-body-1" [matTooltip]="summaryProperty.desc" [matTooltipShowDelay]="400">{{ summaryProperty.key }}:</span>
53            <ng-container *ngIf="summaryProperty.simpleValue">
54              {{ summaryProperty.simpleValue }}
55            </ng-container>
56            <ng-container *ngIf="summaryProperty.layerValues">
57              &ngsp;
58              <ng-container *ngFor="let layer of summaryProperty.layerValues; index as i">
59                <button
60                  mat-button
61                  color="primary"
62                  [matTooltip]="layer.name"
63                  (click)="onIdClicked(layer.nodeId)">
64                  {{ layer.layerId }}
65                </button>
66                {{(i === summaryProperty.layerValues.length - 1) ? '' : ', '}}
67              </ng-container>
68            </ng-container>
69          </span>
70        </div>
71      </div>
72
73      <mat-divider></mat-divider>
74
75      <div class="group geometry">
76        <h3 class="group-header mat-subheading-2">Geometry</h3>
77        <div class="left-column">
78          <p class="column-header mat-small">Calculated</p>
79          <p
80            class="property mat-body-1"
81            matTooltip="Requested transform multiplied by any parent transforms.
82                Used on calculated crop to generate final bounds.">Transform:</p>
83          <transform-matrix
84            *ngIf="properties.calcTransform?.getAllChildren().length > 0"
85            [matTooltip]="getTransformType(properties.calcTransform)"
86            [matrix]="getTransformMatrix(properties.calcTransform)"></transform-matrix>
87          <p class="mat-body-2 crop">
88            <span
89              class="mat-body-1"
90              matTooltip="Raw value read from proto.bounds. This is the buffer size or
91                  requested crop, cropped by parent bounds.">Crop:</span>
92            &ngsp;
93            {{ properties.calcCrop }}
94          </p>
95
96          <p class="mat-body-2 final-bounds">
97            <span
98              class="mat-body-1"
99              matTooltip="Raw value read from proto.screenBounds. This is the calculated crop
100                  transformed by calculated transform."
101              >Final Bounds:</span
102            >
103            &ngsp;
104            {{ properties.finalBounds }}
105          </p>
106        </div>
107        <div class="right-column">
108          <p class="column-header mat-small">Requested</p>
109          <p
110            class="property mat-body-1"
111            matTooltip="Transform requested for this layer, not accounting for parent transforms.">Transform:</p>
112          <transform-matrix
113            *ngIf="properties.reqTransform?.getAllChildren().length > 0"
114            [matTooltip]="getTransformType(properties.reqTransform)"
115            [matrix]="getTransformMatrix(properties.reqTransform)"></transform-matrix>
116        </div>
117      </div>
118
119      <mat-divider></mat-divider>
120
121      <div class="group buffer">
122        <h3 class="group-header mat-subheading-2">Buffer</h3>
123        <div class="left-column">
124          <p
125            class="mat-body-2 size"
126            matTooltip="Width, height, stride and format of active buffer, if available.">
127            <span class="mat-body-1">Size:</span>
128            &ngsp;
129            {{ properties.bufferSize }}
130          </p>
131          <p class="mat-body-2 frame-number">
132            <span class="mat-body-1">Frame Number:</span>
133            &ngsp;
134            {{ properties.frameNumber }}
135          </p>
136          <p class="mat-body-2 transform">
137            <span
138              class="mat-body-1"
139              matTooltip="Rotates or flips the buffer in place. Used with display transform
140                  hint to cancel out any buffer transformation when sending to
141                  HWC."
142              >Transform:</span
143            >
144            &ngsp;
145            {{ properties.bufferTransformType }}
146          </p>
147        </div>
148        <div class="right-column">
149          <p class="mat-body-2 dest-frame">
150            <span
151              class="mat-body-1"
152              matTooltip="Scales buffer to the frame by overriding the requested transform
153                  for this item.">Destination Frame:</span>
154            &ngsp;
155            {{ properties.destinationFrame }}
156          </p>
157          <p *ngIf="properties.ignoreDestinationFrame" class="mat-body-2 ignore-frame">
158            Destination Frame ignored because item has eIgnoreDestinationFrame flag set.
159          </p>
160        </div>
161      </div>
162
163      <mat-divider></mat-divider>
164
165      <div class="group hierarchy-info">
166        <h3 class="group-header mat-subheading-2">Hierarchy</h3>
167        <div class="left-column">
168          <p class="mat-body-2 z-order">
169            <span class="mat-body-1">Z-order:</span>
170            &ngsp;
171            {{ properties.z }}
172          </p>
173          <p class="mat-body-2 rel-parent inline">
174            <span
175              class="mat-body-1"
176              matTooltip="Item is z-ordered relative to its relative parents but its bounds
177                  and other properties are inherited from its parents."
178              >Relative Parent:</span>
179            &ngsp;
180            <ng-container *ngIf="!properties.relativeParent.nodeId">
181              {{ properties.relativeParent }}
182            </ng-container>
183            <ng-container *ngIf="properties.relativeParent.nodeId">
184              <button
185                mat-button
186                color="primary"
187                [matTooltip]="properties.relativeParent.name"
188                (click)="onIdClicked(properties.relativeParent.nodeId)">
189                {{ properties.relativeParent.layerId }}
190              </button>
191            </ng-container>
192          </p>
193          <span class="mat-body-2 rel-children inline">
194            <span class="mat-body-1">Relative Children:</span>
195            &ngsp;
196            <ng-container *ngIf="properties.relativeChildren.length === 0">
197              none
198            </ng-container>
199            <ng-container *ngFor="let layer of properties.relativeChildren; index as i">
200              <button
201                mat-button
202                color="primary"
203                [matTooltip]="layer.name"
204                (click)="onIdClicked(layer.nodeId)">
205                {{ layer.layerId }}
206              </button>
207              {{(i === properties.relativeChildren.length - 1) ? '' : ', '}}
208            </ng-container>
209          </span>
210        </div>
211      </div>
212
213      <mat-divider></mat-divider>
214
215      <div class="group effects">
216        <h3 class="group-header mat-subheading-2">Effects</h3>
217        <div class="left-column">
218          <p class="column-header mat-small">Calculated</p>
219          <p class="mat-body-2 color">
220            <span
221              class="mat-body-1"
222              matTooltip="Final color - alpha may be inherited from a parent layer.">Color:</span>
223            &ngsp;
224            {{ properties.calcColor }}
225          </p>
226          <p class="mat-body-2 corner-radius">
227            <span
228              class="mat-body-1"
229              matTooltip="Final corner radius - may be affected by parent corner radii.">Corner Radius:</span>
230            &ngsp;
231            {{ properties.calcCornerRadius }}
232          </p>
233          <p class="mat-body-2 shadow">
234            <span class="mat-body-1">Shadow Radius:</span>
235            &ngsp;
236            {{ properties.calcShadowRadius }}
237          </p>
238          <p class="mat-body-2">
239            <span
240              class="mat-body-1"
241              matTooltip="Crop used to define the bounds of the corner radii. If the bounds
242                  are greater than the item bounds then the rounded corner will not
243                  be visible."
244              >Corner Radius Crop:</span
245            >
246            &ngsp;
247            {{ properties.calcCornerRadiusCrop }}
248          </p>
249          <p class="mat-body-2 blur">
250            <span class="mat-body-1">Blur Radius:</span>
251            &ngsp;
252            {{ properties.backgroundBlurRadius }}
253          </p>
254        </div>
255        <div class="right-column">
256          <p class="column-header mat-small">Requested</p>
257          <p class="mat-body-2">
258            <span
259              class="mat-body-1"
260              matTooltip="Requested color and alpha for this layer.">Color:</span>
261            &ngsp;
262            {{ properties.reqColor }}
263          </p>
264          <p class="mat-body-2 corner-radius">
265            <span
266              class="mat-body-1"
267              matTooltip="Requested corner radius not accounting for any parent values.">Corner Radius:</span>
268            &ngsp;
269            {{ properties.reqCornerRadius }}
270          </p>
271        </div>
272      </div>
273
274      <mat-divider></mat-divider>
275
276      <div class="group inputs">
277        <h3 class="group-header mat-subheading-2">Input</h3>
278        <ng-container *ngIf="properties.hasInputChannel">
279          <div class="left-column">
280            <p class="property mat-body-1">To Display Transform:</p>
281            <transform-matrix
282              *ngIf="properties.inputTransform?.getAllChildren().length > 0"
283              [matTooltip]="getTransformType(properties.inputTransform)"
284              [matrix]="getTransformMatrix(properties.inputTransform)"></transform-matrix>
285            <p class="mat-body-2">
286              <span class="mat-body-1">Touchable Region:</span>
287              &ngsp;
288              {{ properties.inputRegion }}
289            </p>
290          </div>
291          <div class="right-column">
292            <p class="column-header mat-small">Config</p>
293            <p class="mat-body-2 focusable">
294              <span class="mat-body-1">Focusable:</span>
295              &ngsp;
296              {{ properties.focusable }}
297            </p>
298            <p class="mat-body-2 crop-touch-region">
299              <span class="mat-body-1">Crop touch region with item:</span>
300              &ngsp;
301              {{ properties.cropTouchRegionWithItem }}
302            </p>
303            <p class="mat-body-2 replace-touch-region">
304              <span class="mat-body-1">Replace touch region with crop:</span>
305              &ngsp;
306              {{ properties.replaceTouchRegionWithCrop }}
307            </p>
308            <p class="mat-body-2 input-config">
309              <span class="mat-body-1">Input Config:</span>
310              &ngsp;
311              {{ properties.inputConfig }}
312            </p>
313          </div>
314        </ng-container>
315        <div *ngIf="!properties.hasInputChannel" class="left-column">
316          <p class="mat-body-2">
317            <span class="mat-body-1">Input Channel:</span>
318            &ngsp; not set
319          </p>
320        </div>
321      </div>
322    </div>
323  `,
324  styles: [
325    `
326      :host collapsible-section-title {
327        padding-bottom: 8px;
328      }
329      .placeholder-text {
330        padding: 8px 12px;
331      }
332
333      .property-groups-content {
334        overflow-y: auto;
335        padding: 0px 12px;
336      }
337
338      .group {
339        display: flex;
340        flex-direction: row;
341        padding: 8px;
342      }
343
344      .group-header {
345        width: 80px;
346        color: gray;
347      }
348
349      .left-column {
350        flex: 1;
351        padding: 0 5px;
352      }
353
354      .right-column {
355        flex: 1;
356        border: 1px solid var(--border-color);
357        border-left-width: 5px;
358        padding: 0 5px;
359      }
360
361      .column-header {
362        color: gray;
363      }
364
365      .summary {
366        display: block;
367      }
368    `,
369    inlineButtonStyle,
370    viewerCardInnerStyle,
371  ],
372})
373export class SurfaceFlingerPropertyGroupsComponent {
374  @Input() properties: SfCuratedProperties | undefined;
375
376  @Output() collapseButtonClicked = new EventEmitter();
377
378  constructor(@Inject(ElementRef) private elementRef: ElementRef) {}
379
380  getTransformType(transformNode: UiPropertyTreeNode): string {
381    const typeFlags = transformNode.formattedValue();
382    return typeFlags !== 'null' ? typeFlags : 'IDENTITY';
383  }
384
385  getTransformMatrix(transformNode: UiPropertyTreeNode): UiPropertyTreeNode {
386    return assertDefined(transformNode.getChildByName('matrix'));
387  }
388
389  onIdClicked(layerNodeId: string) {
390    const event = new CustomEvent(ViewerEvents.HighlightedIdChange, {
391      bubbles: true,
392      detail: {id: layerNodeId},
393    });
394    this.elementRef.nativeElement.dispatchEvent(event);
395  }
396}
397