1/* 2 * Copyright (C) 2022 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 {Component, ElementRef, Inject, Input} from '@angular/core'; 17import {TraceTreeNode} from 'trace/trace_tree_node'; 18import {PropertiesTreeNode, Terminal} from 'viewers/common/ui_tree_utils'; 19import {UserOptions} from 'viewers/common/user_options'; 20import {ViewerEvents} from 'viewers/common/viewer_events'; 21 22@Component({ 23 selector: 'properties-view', 24 template: ` 25 <div class="view-header" [class.view-header-with-property-groups]="displayPropertyGroups"> 26 <div class="title-filter"> 27 <h2 class="properties-title mat-title">Properties</h2> 28 29 <mat-form-field> 30 <mat-label>Filter...</mat-label> 31 32 <input matInput [(ngModel)]="filterString" (ngModelChange)="filterTree()" name="filter" /> 33 </mat-form-field> 34 </div> 35 36 <div class="view-controls"> 37 <mat-checkbox 38 *ngFor="let option of objectKeys(userOptions)" 39 color="primary" 40 [(ngModel)]="userOptions[option].enabled" 41 (ngModelChange)="updateTree()" 42 [matTooltip]="userOptions[option].tooltip ?? ''" 43 >{{ userOptions[option].name }}</mat-checkbox 44 > 45 </div> 46 47 <property-groups 48 *ngIf="itemIsSelected() && displayPropertyGroups" 49 class="property-groups" 50 [item]="selectedFlickerItem"></property-groups> 51 </div> 52 53 <mat-divider></mat-divider> 54 55 <div class="properties-content"> 56 <h3 57 *ngIf="objectKeys(propertiesTree).length > 0 && isProtoDump" 58 class="properties-title mat-subheading-2"> 59 Properties - Proto Dump 60 </h3> 61 62 <div class="tree-wrapper"> 63 <tree-view 64 *ngIf="objectKeys(propertiesTree).length > 0" 65 [item]="propertiesTree" 66 [showNode]="showNode" 67 [isLeaf]="isLeaf" 68 [isAlwaysCollapsed]="true"></tree-view> 69 </div> 70 </div> 71 `, 72 styles: [ 73 ` 74 .view-header { 75 display: flex; 76 flex-direction: column; 77 overflow-y: auto; 78 margin-bottom: 12px; 79 } 80 81 .view-header-with-property-groups { 82 flex: 3; 83 } 84 85 .title-filter { 86 display: flex; 87 flex-direction: row; 88 flex-wrap: wrap; 89 justify-content: space-between; 90 } 91 92 .view-controls { 93 display: flex; 94 flex-direction: row; 95 flex-wrap: wrap; 96 column-gap: 10px; 97 margin-bottom: 16px; 98 } 99 100 .properties-content { 101 flex: 1; 102 display: flex; 103 flex-direction: column; 104 overflow-y: auto; 105 } 106 107 .property-groups { 108 height: 100%; 109 overflow-y: auto; 110 } 111 112 .tree-wrapper { 113 overflow: auto; 114 } 115 `, 116 ], 117}) 118export class PropertiesComponent { 119 objectKeys = Object.keys; 120 filterString = ''; 121 122 @Input() userOptions: UserOptions = {}; 123 @Input() propertiesTree: PropertiesTreeNode = {}; 124 @Input() selectedFlickerItem: TraceTreeNode | null = null; 125 @Input() displayPropertyGroups = false; 126 @Input() isProtoDump = false; 127 128 constructor(@Inject(ElementRef) private elementRef: ElementRef) {} 129 130 filterTree() { 131 const event: CustomEvent = new CustomEvent(ViewerEvents.PropertiesFilterChange, { 132 bubbles: true, 133 detail: {filterString: this.filterString}, 134 }); 135 this.elementRef.nativeElement.dispatchEvent(event); 136 } 137 138 updateTree() { 139 const event: CustomEvent = new CustomEvent(ViewerEvents.PropertiesUserOptionsChange, { 140 bubbles: true, 141 detail: {userOptions: this.userOptions}, 142 }); 143 this.elementRef.nativeElement.dispatchEvent(event); 144 } 145 146 showNode(item: any) { 147 return ( 148 !(item instanceof Terminal) && 149 !(item.name instanceof Terminal) && 150 !(item.propertyKey instanceof Terminal) 151 ); 152 } 153 154 isLeaf(item: any) { 155 return ( 156 !item.children || 157 item.children.length === 0 || 158 item.children.filter((c: any) => !(c instanceof Terminal)).length === 0 159 ); 160 } 161 162 itemIsSelected() { 163 return this.selectedFlickerItem && Object.keys(this.selectedFlickerItem).length > 0; 164 } 165} 166