(Rects View Review Changes) Create SF viewer.
Review changes for ag/19482843 (in separate CL as requested). Bug: b/238089034 Test: npm run test:all Change-Id: I9d2f99090f2e2125271b702c8a1dc409f112b776
This commit is contained in:
@@ -31,7 +31,6 @@ import { PropertiesComponent } from "viewers/properties.component";
|
||||
import { RectsComponent } from "viewers/rects.component";
|
||||
import { TraceViewHeaderComponent } from "./components/trace_view_header.component";
|
||||
import { TraceViewComponent } from "./components/trace_view.component";
|
||||
import { CanvasService } from "viewers/canvas.service";
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -70,7 +69,6 @@ import { CanvasService } from "viewers/canvas.service";
|
||||
MatSliderModule,
|
||||
MatRadioModule
|
||||
],
|
||||
providers: [CanvasService],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
import { AdbProxyComponent } from "./adb_proxy.component";
|
||||
import { proxyClient, ProxyState } from "../../trace_collection/proxy_client";
|
||||
import { proxyClient, ProxyState } from "trace_collection/proxy_client";
|
||||
import { MatIconModule } from "@angular/material/icon";
|
||||
import { MatFormFieldModule } from "@angular/material/form-field";
|
||||
import { MatInputModule } from "@angular/material/input";
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { MatButtonModule } from "@angular/material/button";
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
import { NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
|
||||
describe("AdbProxyComponent", () => {
|
||||
let fixture: ComponentFixture<AdbProxyComponent>;
|
||||
@@ -40,7 +40,7 @@ describe("AdbProxyComponent", () => {
|
||||
MatButtonModule
|
||||
],
|
||||
declarations: [AdbProxyComponent],
|
||||
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
}).compileComponents();
|
||||
fixture = TestBed.createComponent(AdbProxyComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Component, Input, Output, EventEmitter } from "@angular/core";
|
||||
import { proxyClient, ProxyClient, ProxyState } from "../../trace_collection/proxy_client";
|
||||
import { proxyClient, ProxyClient, ProxyState } from "trace_collection/proxy_client";
|
||||
|
||||
@Component({
|
||||
selector: "adb-proxy",
|
||||
|
||||
@@ -17,7 +17,7 @@ import { Component, Injector, Inject, ViewEncapsulation, Input } from "@angular/
|
||||
import { createCustomElement } from "@angular/elements";
|
||||
import { TraceCoordinator } from "../trace_coordinator";
|
||||
import { proxyClient, ProxyState } from "trace_collection/proxy_client";
|
||||
import { PersistentStore } from "../../common/persistent_store";
|
||||
import { PersistentStore } from "common/persistent_store";
|
||||
import { ViewerWindowManagerComponent } from "viewers/viewer_window_manager/viewer_window_manager.component";
|
||||
import { ViewerSurfaceFlingerComponent } from "viewers/viewer_surface_flinger/viewer_surface_flinger.component";
|
||||
import { TraceViewComponent } from "./trace_view.component";
|
||||
@@ -36,7 +36,7 @@ import { Viewer } from "viewers/viewer";
|
||||
*ngIf="dataLoaded"
|
||||
step="1"
|
||||
min="0"
|
||||
[max]="traceCoordinator.getTimestamps().length -1"
|
||||
[max]="this.allTimestamps.length-1"
|
||||
aria-label="units"
|
||||
[value]="currentTimestampIndex"
|
||||
(input)="updateCurrentTimestamp($event)"
|
||||
@@ -72,8 +72,9 @@ export class AppComponent {
|
||||
store: PersistentStore = new PersistentStore();
|
||||
@Input() dataLoaded = false;
|
||||
viewersCreated = false;
|
||||
currentTimestamp: Timestamp;
|
||||
currentTimestamp?: Timestamp;
|
||||
currentTimestampIndex = 0;
|
||||
allTimestamps: Timestamp[] = [];
|
||||
|
||||
constructor(
|
||||
@Inject(Injector) injector: Injector
|
||||
@@ -95,6 +96,7 @@ export class AppComponent {
|
||||
|
||||
onDataLoadedChange(dataLoaded: boolean) {
|
||||
if (dataLoaded && !this.viewersCreated) {
|
||||
this.allTimestamps = this.traceCoordinator.getTimestamps();
|
||||
this.traceCoordinator.createViewers();
|
||||
this.createViewerElements();
|
||||
this.currentTimestampIndex = 0;
|
||||
@@ -108,8 +110,10 @@ export class AppComponent {
|
||||
const viewersDiv = document.querySelector("div#viewers")!;
|
||||
viewersDiv.innerHTML = "";
|
||||
|
||||
let cardCounter = 0;
|
||||
this.traceCoordinator.getViewers().forEach((viewer: Viewer) => {
|
||||
const traceView = document.createElement("trace-view");
|
||||
(traceView as any).title = viewer.getTitle();
|
||||
(traceView as any).dependencies = viewer.getDependencies();
|
||||
(traceView as any).showTrace = true;
|
||||
traceView.addEventListener("saveTraces", ($event: any) => {
|
||||
@@ -118,15 +122,15 @@ export class AppComponent {
|
||||
viewersDiv.appendChild(traceView);
|
||||
|
||||
const traceCard = traceView.querySelector(".trace-card")!;
|
||||
traceCard.id = `card-${viewer.getDependencies()}`;
|
||||
traceCard.id = `card-${cardCounter}`;
|
||||
(traceView as any).cardId = cardCounter;
|
||||
cardCounter++;
|
||||
|
||||
const traceCardContent = traceCard.querySelector(".trace-card-content")!;
|
||||
const view = viewer.getView();
|
||||
(view as any).showTrace = (traceView as any).showTrace;
|
||||
traceCardContent.appendChild(view);
|
||||
});
|
||||
this.currentTimestampIndex = 0;
|
||||
this.notifyCurrentTimestamp();
|
||||
}
|
||||
|
||||
updateCurrentTimestamp(event: MatSliderChange) {
|
||||
@@ -137,13 +141,13 @@ export class AppComponent {
|
||||
}
|
||||
|
||||
public notifyCurrentTimestamp() {
|
||||
this.currentTimestamp = this.traceCoordinator.getTimestamps()[this.currentTimestampIndex];
|
||||
this.currentTimestamp = this.allTimestamps[this.currentTimestampIndex];
|
||||
this.traceCoordinator.notifyCurrentTimestamp(this.currentTimestamp);
|
||||
}
|
||||
|
||||
public toggleTimestamp() {
|
||||
if (this.currentTimestampIndex===0) {
|
||||
this.currentTimestampIndex = this.traceCoordinator.getTimestamps().length-1;
|
||||
this.currentTimestampIndex = this.allTimestamps.length-1;
|
||||
} else {
|
||||
this.currentTimestampIndex = 0;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import { MatListModule } from "@angular/material/list";
|
||||
import { MatButtonModule } from "@angular/material/button";
|
||||
import { MatProgressBarModule } from "@angular/material/progress-bar";
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
import { NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
|
||||
describe("CollectTracesComponent", () => {
|
||||
let fixture: ComponentFixture<CollectTracesComponent>;
|
||||
@@ -47,7 +47,7 @@ describe("CollectTracesComponent", () => {
|
||||
WebAdbComponent,
|
||||
TraceConfigComponent,
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
}).compileComponents();
|
||||
fixture = TestBed.createComponent(CollectTracesComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Component, Inject, Input, Output, EventEmitter, NgZone } from "@angular/core";
|
||||
import { Component, Inject, Input, Output, EventEmitter, OnInit, OnDestroy } from "@angular/core";
|
||||
import { ProxyConnection } from "trace_collection/proxy_connection";
|
||||
import { Connection } from "trace_collection/connection";
|
||||
import { setTraces } from "trace_collection/set_traces";
|
||||
import { ProxyState } from "../../trace_collection/proxy_client";
|
||||
import { traceConfigurations, configMap, SelectionConfiguration, EnableConfiguration } from "../../trace_collection/trace_collection_utils";
|
||||
import { ProxyState } from "trace_collection/proxy_client";
|
||||
import { traceConfigurations, configMap, SelectionConfiguration, EnableConfiguration } from "trace_collection/trace_collection_utils";
|
||||
import { TraceCoordinator } from "app/trace_coordinator";
|
||||
import { PersistentStore } from "../../common/persistent_store";
|
||||
import { PersistentStore } from "common/persistent_store";
|
||||
|
||||
|
||||
@Component({
|
||||
@@ -33,9 +33,9 @@ import { PersistentStore } from "../../common/persistent_store";
|
||||
|
||||
<div class="set-up-adb" *ngIf="!connect.adbSuccess()">
|
||||
<button id="proxy-tab" mat-raised-button [ngClass]="tabClass(true)" (click)="displayAdbProxyTab()">ADB Proxy</button>
|
||||
<button id="web-tab" mat-raised-button [ngClass]="tabClass(false)" (click)="displayWebAdbTab()">Web ADB</button>
|
||||
<!-- <button id="web-tab" mat-raised-button [ngClass]="tabClass(false)" (click)="displayWebAdbTab()">Web ADB</button> -->
|
||||
<adb-proxy *ngIf="isAdbProxy" [(proxy)]="connect.proxy!" (addKey)="onAddKey($event)"></adb-proxy>
|
||||
<web-adb *ngIf="!isAdbProxy"></web-adb>
|
||||
<!-- <web-adb *ngIf="!isAdbProxy"></web-adb> TODO: fix web adb workflow -->
|
||||
</div>
|
||||
|
||||
<div id="devices-connecting" *ngIf="connect.isDevicesState()">
|
||||
@@ -116,28 +116,20 @@ import { PersistentStore } from "../../common/persistent_store";
|
||||
".mat-checkbox-checked .mat-checkbox-background {transform: scale(0.7); font-size: 10;}"
|
||||
]
|
||||
})
|
||||
export class CollectTracesComponent {
|
||||
export class CollectTracesComponent implements OnInit, OnDestroy {
|
||||
objectKeys = Object.keys;
|
||||
isAdbProxy = true;
|
||||
traceConfigurations = traceConfigurations;
|
||||
connect: Connection = new ProxyConnection();
|
||||
setTraces = setTraces;
|
||||
|
||||
@Input()
|
||||
store: PersistentStore = new PersistentStore();
|
||||
|
||||
@Input()
|
||||
traceCoordinator: TraceCoordinator;
|
||||
|
||||
@Output()
|
||||
traceCoordinatorChange = new EventEmitter<TraceCoordinator>();
|
||||
|
||||
dataLoaded = false;
|
||||
|
||||
@Output()
|
||||
dataLoadedChange = new EventEmitter<boolean>();
|
||||
@Input() store!: PersistentStore;
|
||||
@Input() traceCoordinator!: TraceCoordinator;
|
||||
|
||||
constructor(@Inject(NgZone) private ngZone: NgZone) {
|
||||
@Output() dataLoadedChange = new EventEmitter<boolean>();
|
||||
|
||||
ngOnInit() {
|
||||
if (this.isAdbProxy) {
|
||||
this.connect = new ProxyConnection();
|
||||
} else {
|
||||
@@ -278,11 +270,8 @@ export class CollectTracesComponent {
|
||||
this.traceCoordinator.clearData();
|
||||
|
||||
await this.traceCoordinator.addTraces(this.connect.adbData());
|
||||
|
||||
this.ngZone.run(() => {
|
||||
this.dataLoaded = true;
|
||||
this.dataLoadedChange.emit(this.dataLoaded);
|
||||
});
|
||||
this.dataLoaded = true;
|
||||
this.dataLoadedChange.emit(this.dataLoaded);
|
||||
console.log("finished loading data!");
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import { MatFormFieldModule } from "@angular/material/form-field";
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { MatInputModule } from "@angular/material/input";
|
||||
import { MatSelectModule } from "@angular/material/select";
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
import { NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
|
||||
describe("TraceConfigComponent", () => {
|
||||
let fixture: ComponentFixture<TraceConfigComponent>;
|
||||
@@ -39,7 +39,7 @@ describe("TraceConfigComponent", () => {
|
||||
BrowserAnimationsModule
|
||||
],
|
||||
declarations: [TraceConfigComponent],
|
||||
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
}).compileComponents();
|
||||
fixture = TestBed.createComponent(TraceConfigComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Component, Input } from "@angular/core";
|
||||
import { EnableConfiguration, SelectionConfiguration, TraceConfiguration } from "../../trace_collection/trace_collection_utils";
|
||||
import { EnableConfiguration, SelectionConfiguration, TraceConfiguration } from "trace_collection/trace_collection_utils";
|
||||
|
||||
@Component({
|
||||
selector: "trace-config",
|
||||
|
||||
@@ -29,8 +29,10 @@ import { TraceType } from "common/trace/trace_type";
|
||||
<mat-card-header>
|
||||
<mat-card-title class="trace-card-title" *ngIf="dependencies">
|
||||
<trace-view-header
|
||||
[title]="title"
|
||||
[(showTrace)]="showTrace"
|
||||
[dependencies]="dependencies"
|
||||
[cardId]="cardId"
|
||||
(saveTraceChange)="onSaveTraces($event)"
|
||||
></trace-view-header>
|
||||
</mat-card-title>
|
||||
@@ -41,14 +43,11 @@ import { TraceType } from "common/trace/trace_type";
|
||||
`,
|
||||
})
|
||||
export class TraceViewComponent {
|
||||
@Input()
|
||||
dependencies: TraceType[];
|
||||
|
||||
@Input()
|
||||
showTrace: boolean;
|
||||
|
||||
@Output()
|
||||
saveTraces = new EventEmitter<TraceType[]>();
|
||||
@Input() title!: string;
|
||||
@Input() dependencies!: TraceType[];
|
||||
@Input() showTrace = true;
|
||||
@Input() cardId = 0;
|
||||
@Output() saveTraces = new EventEmitter<TraceType[]>();
|
||||
|
||||
TRACE_INFO = TRACE_INFO;
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ import { ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
import { TraceViewHeaderComponent } from "./trace_view_header.component";
|
||||
import { MatIconModule } from "@angular/material/icon";
|
||||
import { MatButtonModule } from "@angular/material/button";
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
import { TraceType } from "common/trace/trace_type";
|
||||
|
||||
describe("TraceViewHeaderComponent", () => {
|
||||
@@ -33,8 +32,7 @@ describe("TraceViewHeaderComponent", () => {
|
||||
MatIconModule,
|
||||
MatButtonModule
|
||||
],
|
||||
declarations: [TraceViewHeaderComponent],
|
||||
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
|
||||
declarations: [TraceViewHeaderComponent]
|
||||
}).compileComponents();
|
||||
fixture = TestBed.createComponent(TraceViewHeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
@@ -85,6 +83,7 @@ describe("TraceViewHeaderComponent", () => {
|
||||
});
|
||||
|
||||
it("check that title is displayed", () => {
|
||||
component.title = "Surface Flinger, Window Manager";
|
||||
fixture.detectChanges();
|
||||
const title = htmlElement.querySelector(".trace-card-title-text");
|
||||
expect(title).toBeTruthy();
|
||||
|
||||
@@ -33,7 +33,7 @@ import html2canvas from "html2canvas";
|
||||
</button>
|
||||
<mat-icon id="dep-icon" *ngFor="let dep of dependencies" aria-hidden="true" class="icon-button">{{TRACE_INFO[dep].icon}}</mat-icon>
|
||||
<span class="trace-card-title-text">
|
||||
{{getTitle()}}
|
||||
{{title}}
|
||||
</span>
|
||||
<button id="save-btn" class="icon-button" (click)="saveTraces()">
|
||||
<mat-icon aria-hidden="true">save_alt</mat-icon>
|
||||
@@ -47,17 +47,13 @@ import html2canvas from "html2canvas";
|
||||
]
|
||||
})
|
||||
export class TraceViewHeaderComponent {
|
||||
@Input()
|
||||
dependencies: TraceType[];
|
||||
@Input() title?: string;
|
||||
@Input() dependencies?: TraceType[];
|
||||
@Input() showTrace = true;
|
||||
@Input() cardId!: number ;
|
||||
|
||||
@Input()
|
||||
showTrace = true;
|
||||
|
||||
@Output()
|
||||
showTraceChange = new EventEmitter<boolean>();
|
||||
|
||||
@Output()
|
||||
saveTraceChange = new EventEmitter<TraceType[]>();
|
||||
@Output() showTraceChange = new EventEmitter<boolean>();
|
||||
@Output() saveTraceChange = new EventEmitter<TraceType[]>();
|
||||
|
||||
TRACE_INFO = TRACE_INFO;
|
||||
|
||||
@@ -66,25 +62,12 @@ export class TraceViewHeaderComponent {
|
||||
this.showTraceChange.emit(this.showTrace);
|
||||
}
|
||||
|
||||
getTitle() {
|
||||
if (this.dependencies === undefined) {
|
||||
return "Unknown Trace";
|
||||
}
|
||||
let title = `${TRACE_INFO[this.dependencies[0]].name}`;
|
||||
if (this.dependencies.length > 1) {
|
||||
for (const dep of this.dependencies.slice(1)) {
|
||||
title += `, ${TRACE_INFO[dep].name}`;
|
||||
}
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
public saveTraces() {
|
||||
this.saveTraceChange.emit(this.dependencies);
|
||||
}
|
||||
|
||||
public takeScreenshot() {
|
||||
const el = document.querySelector(`#card-${this.dependencies}`);
|
||||
const el = document.querySelector(`#card-${this.cardId}`);
|
||||
if (el) {
|
||||
html2canvas((el as HTMLElement)).then((canvas) => {
|
||||
const uri = canvas.toDataURL();
|
||||
|
||||
@@ -17,7 +17,7 @@ import {ComponentFixture, TestBed} from "@angular/core/testing";
|
||||
import {UploadTracesComponent} from "./upload_traces.component";
|
||||
import { MatCardModule } from "@angular/material/card";
|
||||
|
||||
describe("CollectTracesComponent", () => {
|
||||
describe("UploadTracesComponent", () => {
|
||||
let fixture: ComponentFixture<UploadTracesComponent>;
|
||||
let component: UploadTracesComponent;
|
||||
let htmlElement: HTMLElement;
|
||||
|
||||
@@ -74,16 +74,11 @@ import { LoadedTrace } from "app/loaded_trace";
|
||||
]
|
||||
})
|
||||
export class UploadTracesComponent {
|
||||
@Input()
|
||||
traceCoordinator: TraceCoordinator;
|
||||
|
||||
@Output()
|
||||
traceCoordinatorChange = new EventEmitter<TraceCoordinator>();
|
||||
@Input() traceCoordinator!: TraceCoordinator;
|
||||
|
||||
dataLoaded = false;
|
||||
|
||||
@Output()
|
||||
dataLoadedChange = new EventEmitter<boolean>();
|
||||
@Output() dataLoadedChange = new EventEmitter<boolean>();
|
||||
|
||||
constructor(@Inject(NgZone) private ngZone: NgZone) {}
|
||||
|
||||
@@ -121,7 +116,6 @@ export class UploadTracesComponent {
|
||||
this.dataLoaded = false;
|
||||
this.loadedTraces = [];
|
||||
this.dataLoadedChange.emit(this.dataLoaded);
|
||||
this.traceCoordinatorChange.emit(this.traceCoordinator);
|
||||
}
|
||||
|
||||
public onFileDragIn(e: DragEvent) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TraceType } from "../common/trace/trace_type";
|
||||
import { TraceType } from "common/trace/trace_type";
|
||||
|
||||
export interface LoadedTrace {
|
||||
name: string;
|
||||
|
||||
@@ -22,7 +22,6 @@ import { Viewer } from "viewers/viewer";
|
||||
import { ViewerFactory } from "viewers/viewer_factory";
|
||||
import { LoadedTrace } from "app/loaded_trace";
|
||||
import { TRACE_INFO } from "./trace_info";
|
||||
import { bigIntMath } from "common/utils/bigint_utils";
|
||||
|
||||
class TraceCoordinator {
|
||||
private parsers: Parser[];
|
||||
@@ -105,19 +104,9 @@ class TraceCoordinator {
|
||||
|
||||
this.parsers.forEach(parser => {
|
||||
const targetTimestamp = timestamp;
|
||||
const parserTimestamps = parser.getTimestamps(timestamp.getType());
|
||||
|
||||
const closestTimestamp = parserTimestamps?.reduce((prev, curr) => {
|
||||
const prevDiff = bigIntMath.abs(prev.getValueNs() - targetTimestamp.getValueNs());
|
||||
const currDiff = bigIntMath.abs(curr.getValueNs() - targetTimestamp.getValueNs());
|
||||
return currDiff < prevDiff ? curr : prev;
|
||||
});
|
||||
|
||||
if (closestTimestamp) {
|
||||
const entry = parser.getTraceEntry(closestTimestamp);
|
||||
if (entry != undefined) {
|
||||
traceEntries.set(parser.getTraceType(), entry);
|
||||
}
|
||||
const entry = parser.getTraceEntry(targetTimestamp);
|
||||
if (entry !== undefined) {
|
||||
traceEntries.set(parser.getTraceType(), entry);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TraceType } from "../common/trace/trace_type";
|
||||
import { TraceType } from "common/trace/trace_type";
|
||||
|
||||
const WINDOW_MANAGER_ICON = "view_compact";
|
||||
const SURFACE_FLINGER_ICON = "filter_none";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TraceType } from "../common/trace/trace_type";
|
||||
import { TraceType } from "common/trace/trace_type";
|
||||
|
||||
const WINDOW_MANAGER_ICON = "view_compact";
|
||||
const SURFACE_FLINGER_ICON = "filter_none";
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export const bigIntMath = {
|
||||
abs(x: bigint) {
|
||||
return x < 0n ? -x : x;
|
||||
}
|
||||
};
|
||||
@@ -51,6 +51,14 @@ button {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.card-grid {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
mat-checkbox {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ describe("Viewer SurfaceFlinger", () => {
|
||||
const loadData = element(by.css(".load-btn"));
|
||||
loadData.click();
|
||||
|
||||
const surfaceFlingerCard: ElementFinder = element(by.css("#card-2"));
|
||||
const surfaceFlingerCard: ElementFinder = element(by.css(".trace-card"));
|
||||
expect(surfaceFlingerCard.getText()).toContain("Surface Flinger");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { PersistentStore } from "../common/persistent_store";
|
||||
import { PersistentStore } from "common/persistent_store";
|
||||
import { configMap, TRACES } from "./trace_collection_utils";
|
||||
import { setTraces, SetTraces } from "./set_traces";
|
||||
import { Device } from "./connection";
|
||||
|
||||
@@ -13,15 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Injectable } from "@angular/core";
|
||||
import {Rectangle } from "ui_data/ui_data_surface_flinger";
|
||||
import { Rectangle } from "viewers/viewer_surface_flinger/ui_data";
|
||||
import * as THREE from "three";
|
||||
import { CSS2DRenderer, CSS2DObject } from "three/examples/jsm/renderers/CSS2DRenderer";
|
||||
|
||||
@Injectable()
|
||||
export class CanvasService {
|
||||
initialise() {
|
||||
export class CanvasGraphics {
|
||||
constructor() {
|
||||
//set up camera
|
||||
const left = -this.cameraHalfWidth,
|
||||
right = this.cameraHalfWidth,
|
||||
@@ -32,16 +29,17 @@ export class CanvasService {
|
||||
this.camera = new THREE.OrthographicCamera(
|
||||
left,right,top,bottom,near,far
|
||||
);
|
||||
}
|
||||
|
||||
initialise(canvas: HTMLCanvasElement) {
|
||||
// initialise canvas
|
||||
this.canvas = document.getElementById("rects-canvas") as HTMLCanvasElement;
|
||||
if (!this.canvas) return;
|
||||
this.canvas = canvas;
|
||||
}
|
||||
|
||||
refreshCanvas() {
|
||||
//set canvas size
|
||||
this.canvas.style.width = "100%";
|
||||
this.canvas.style.height = "40rem";
|
||||
this.canvas!.style.width = "100%";
|
||||
this.canvas!.style.height = "40rem";
|
||||
|
||||
// TODO: click and drag rotation control
|
||||
this.camera.position.set(this.xyCameraPos, this.xyCameraPos, 6);
|
||||
@@ -103,7 +101,7 @@ export class CanvasService {
|
||||
return y;
|
||||
})) - labelYShift;
|
||||
|
||||
this.createRects(
|
||||
this.drawScene(
|
||||
rectCounter,
|
||||
numberOfVisibleRects,
|
||||
visibleDarkFactor,
|
||||
@@ -121,15 +119,15 @@ export class CanvasService {
|
||||
// const gridHelper = new THREE.GridHelper(5);
|
||||
// scene.add(axesHelper, gridHelper)
|
||||
|
||||
renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
|
||||
renderer.setSize(this.canvas!.clientWidth, this.canvas!.clientHeight);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
renderer.render(scene, this.camera);
|
||||
|
||||
labelRenderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
|
||||
labelRenderer.setSize(this.canvas!.clientWidth, this.canvas!.clientHeight);
|
||||
labelRenderer.render(scene, this.camera);
|
||||
}
|
||||
|
||||
private createRects(
|
||||
private drawScene(
|
||||
rectCounter: number,
|
||||
visibleRects: number,
|
||||
visibleDarkFactor:number,
|
||||
@@ -144,12 +142,13 @@ export class CanvasService {
|
||||
) {
|
||||
this.targetObjects = [];
|
||||
this.rects.forEach(rect => {
|
||||
if (this.visibleView && !rect.isVisible ||
|
||||
!this.visibleView && !this.showVirtualDisplays && rect.isDisplay && rect.isVirtual) {
|
||||
document.querySelector(`.label-${rectCounter}`)?.remove();
|
||||
const visibleViewInvisibleRect = this.visibleView && !rect.isVisible;
|
||||
const xrayViewNoVirtualDisplaysVirtualRect = !this.visibleView && !this.showVirtualDisplays && rect.isDisplay && rect.isVirtual;
|
||||
if (visibleViewInvisibleRect || xrayViewNoVirtualDisplaysVirtualRect) {
|
||||
rectCounter++;
|
||||
return;
|
||||
}
|
||||
|
||||
//set colour mapping
|
||||
let planeColor;
|
||||
if (this.highlighted === `${rect.id}`) {
|
||||
@@ -224,7 +223,7 @@ export class CanvasService {
|
||||
|
||||
private setCircleMaterial(planeRect: THREE.Mesh, rect: Rectangle) {
|
||||
const labelCircle = new THREE.CircleGeometry(0.02, 200);
|
||||
const circleMaterial = new THREE.MeshBasicMaterial({color: 0x000000 });
|
||||
const circleMaterial = new THREE.MeshBasicMaterial({ color: 0x000000 });
|
||||
const circle = new THREE.Mesh(labelCircle, circleMaterial);
|
||||
circle.position.set(
|
||||
planeRect.position.x + rect.width/2 - 0.05,
|
||||
@@ -413,5 +412,5 @@ export class CanvasService {
|
||||
private rects: Rectangle[] = [];
|
||||
private labelElements: HTMLElement[] = [];
|
||||
private targetObjects: any[] = [];
|
||||
private canvas: HTMLCanvasElement;
|
||||
private canvas?: HTMLCanvasElement;
|
||||
}
|
||||
@@ -21,9 +21,8 @@ import { MatCheckboxModule } from "@angular/material/checkbox";
|
||||
import { MatCardModule } from "@angular/material/card";
|
||||
import { MatRadioModule } from "@angular/material/radio";
|
||||
import { MatSliderModule } from "@angular/material/slider";
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
import { Rectangle } from "../ui_data/ui_data_surface_flinger";
|
||||
import { CanvasService } from "./canvas.service";
|
||||
import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
|
||||
import { Rectangle } from "./viewer_surface_flinger/ui_data";
|
||||
|
||||
describe("RectsComponent", () => {
|
||||
let component: TestHostComponent;
|
||||
@@ -40,8 +39,7 @@ describe("RectsComponent", () => {
|
||||
MatRadioModule
|
||||
],
|
||||
declarations: [RectsComponent, TestHostComponent],
|
||||
providers: [CanvasService],
|
||||
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
@@ -64,10 +62,10 @@ describe("RectsComponent", () => {
|
||||
|
||||
it("check that layer separation slider causes view to change", () => {
|
||||
const slider = htmlElement.querySelector("mat-slider");
|
||||
spyOn(component.rectsComponent.canvasService, "updateLayerSeparation");
|
||||
spyOn(component.rectsComponent.canvasGraphics, "updateLayerSeparation");
|
||||
slider?.dispatchEvent(new MouseEvent("mousedown"));
|
||||
fixture.detectChanges();
|
||||
expect(component.rectsComponent.canvasService.updateLayerSeparation).toHaveBeenCalled();
|
||||
expect(component.rectsComponent.canvasGraphics.updateLayerSeparation).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("check that rects canvas is rendered", () => {
|
||||
@@ -101,24 +99,23 @@ describe("RectsComponent", () => {
|
||||
stackId: 0,
|
||||
}
|
||||
]);
|
||||
spyOn(component.rectsComponent, "updateVariablesBeforeRefresh").and.callThrough();
|
||||
spyOn(component.rectsComponent, "drawRects").and.callThrough();
|
||||
fixture.detectChanges();
|
||||
await new Promise( resolve => setTimeout(resolve, 4000));
|
||||
expect(component.rectsComponent.updateVariablesBeforeRefresh).toHaveBeenCalled();
|
||||
expect(component.rectsComponent.drawRects).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@Component({
|
||||
selector: "host-component",
|
||||
template: "<rects-view [rects]=\"rects ?? []\"></rects-view>"
|
||||
template: "<rects-view [rects]=\"rects\"></rects-view>"
|
||||
})
|
||||
class TestHostComponent {
|
||||
public rects: Rectangle[];
|
||||
public rects: Rectangle[] = [];
|
||||
|
||||
addRects(newRects: Rectangle[]) {
|
||||
this.rects = newRects;
|
||||
}
|
||||
|
||||
@ViewChild(RectsComponent)
|
||||
public rectsComponent: RectsComponent;
|
||||
public rectsComponent!: RectsComponent;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Component, Input, OnChanges, OnDestroy, Inject, NgZone, ElementRef, SimpleChanges } from "@angular/core";
|
||||
import { MatrixUtils } from "common/utils/matrix_utils";
|
||||
import { Point, Rectangle, RectMatrix, RectTransform } from "ui_data/ui_data_surface_flinger";
|
||||
import { Component, Input, OnChanges, OnDestroy, Inject, ElementRef, SimpleChanges } from "@angular/core";
|
||||
import { RectsUtils } from "./rects_utils";
|
||||
import { Point, Rectangle, RectMatrix, RectTransform } from "viewers/viewer_surface_flinger/ui_data";
|
||||
import { interval, Subscription } from "rxjs";
|
||||
import { CanvasService } from "./canvas.service";
|
||||
import { CanvasGraphics } from "./canvas_graphics";
|
||||
import * as THREE from "three";
|
||||
|
||||
@Component({
|
||||
@@ -34,7 +34,7 @@ import * as THREE from "three";
|
||||
max="0.4"
|
||||
aria-label="units"
|
||||
[value]="getLayerSeparation()"
|
||||
(input)="canvasService.updateLayerSeparation($event.value!)"
|
||||
(input)="canvasGraphics.updateLayerSeparation($event.value!)"
|
||||
></mat-slider>
|
||||
<mat-slider
|
||||
step="0.01"
|
||||
@@ -42,24 +42,24 @@ import * as THREE from "three";
|
||||
max="4"
|
||||
aria-label="units"
|
||||
[value]="xyCameraPos()"
|
||||
(input)="canvasService.updateRotation($event.value!)"
|
||||
(input)="canvasGraphics.updateRotation($event.value!)"
|
||||
></mat-slider>
|
||||
<mat-checkbox
|
||||
[hidden]="visibleView()"
|
||||
class="rects-checkbox"
|
||||
[checked]="showVirtualDisplays()"
|
||||
(change)="canvasService.updateVirtualDisplays($event.checked!)"
|
||||
(change)="canvasGraphics.updateVirtualDisplays($event.checked!)"
|
||||
>Show virtual displays</mat-checkbox>
|
||||
</mat-card-header>
|
||||
<mat-card-content class="rects-content">
|
||||
<div class="canvas-container">
|
||||
<div class="zoom-container">
|
||||
<button id="zoom-btn" (click)="canvasService.updateZoom(true)">
|
||||
<button id="zoom-btn" (click)="canvasGraphics.updateZoom(true)">
|
||||
<mat-icon aria-hidden="true">
|
||||
zoom_in
|
||||
</mat-icon>
|
||||
</button>
|
||||
<button id="zoom-btn" (click)="canvasService.updateZoom(false)">
|
||||
<button id="zoom-btn" (click)="canvasGraphics.updateZoom(false)">
|
||||
<mat-icon aria-hidden="true">
|
||||
zoom_out
|
||||
</mat-icon>
|
||||
@@ -91,20 +91,15 @@ import * as THREE from "three";
|
||||
})
|
||||
|
||||
export class RectsComponent implements OnChanges, OnDestroy {
|
||||
@Input()
|
||||
bounds: any;
|
||||
@Input() rects!: Rectangle[];
|
||||
|
||||
@Input()
|
||||
rects: Rectangle[];
|
||||
|
||||
@Input()
|
||||
highlighted = "";
|
||||
@Input() highlighted = "";
|
||||
|
||||
constructor(
|
||||
@Inject(NgZone) private ngZone: NgZone,
|
||||
@Inject(ElementRef) private elementRef: ElementRef,
|
||||
@Inject(CanvasService) public canvasService: CanvasService
|
||||
) {}
|
||||
) {
|
||||
this.canvasGraphics = new CanvasGraphics();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.canvasSubscription) {
|
||||
@@ -115,13 +110,13 @@ export class RectsComponent implements OnChanges, OnDestroy {
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (this.rects.length > 0) {
|
||||
//change in rects so they must undergo transformation and scaling before canvas refreshed
|
||||
this.canvasService.clearLabelElements();
|
||||
this.canvasGraphics.clearLabelElements();
|
||||
this.rects = this.rects.filter(rect => rect.isVisible || rect.isDisplay);
|
||||
this.displayRects = this.rects.filter(rect => rect.isDisplay);
|
||||
this.computeBounds();
|
||||
this.rects = this.rects.map(rect => {
|
||||
if (changes["rects"] && rect.transform) {
|
||||
return MatrixUtils.transformRect(rect.transform.matrix ?? rect.transform, rect);
|
||||
return RectsUtils.transformRect(rect.transform.matrix ?? rect.transform, rect);
|
||||
} else {
|
||||
return rect;
|
||||
}
|
||||
@@ -133,32 +128,31 @@ export class RectsComponent implements OnChanges, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
onRectClick(event:any) {
|
||||
onRectClick(event:PointerEvent) {
|
||||
this.setNormalisedMousePos(event);
|
||||
const raycaster = new THREE.Raycaster();
|
||||
raycaster.setFromCamera(this.mouse, this.canvasService.getCamera());
|
||||
raycaster.setFromCamera(this.mouse, this.canvasGraphics.getCamera());
|
||||
// create an array containing all objects in the scene with which the ray intersects
|
||||
const intersects = raycaster.intersectObjects(this.canvasService.getTargetObjects());
|
||||
const intersects = raycaster.intersectObjects(this.canvasGraphics.getTargetObjects());
|
||||
// if there is one (or more) intersections
|
||||
if (intersects.length > 0){
|
||||
if (this.highlighted === intersects[0].object.name) {
|
||||
this.highlighted = "";
|
||||
this.canvasService.updateHighlighted("");
|
||||
this.canvasGraphics.updateHighlighted("");
|
||||
} else {
|
||||
this.highlighted = intersects[0].object.name;
|
||||
this.canvasService.updateHighlighted(intersects[0].object.name);
|
||||
this.canvasGraphics.updateHighlighted(intersects[0].object.name);
|
||||
}
|
||||
this.ngZone.run(() => {
|
||||
this.updateHighlightedRect();
|
||||
});
|
||||
this.updateHighlightedRect();
|
||||
}
|
||||
}
|
||||
|
||||
setNormalisedMousePos(event:any) {
|
||||
setNormalisedMousePos(event:PointerEvent) {
|
||||
event.preventDefault();
|
||||
const canvasOffset = event.target.getBoundingClientRect();
|
||||
this.mouse.x = ((event.clientX-canvasOffset.left)/event.target.clientWidth) * 2 - 1;
|
||||
this.mouse.y = -((event.clientY-canvasOffset.top)/event.target.clientHeight) * 2 + 1;
|
||||
const canvas = (event.target as Element);
|
||||
const canvasOffset = canvas.getBoundingClientRect();
|
||||
this.mouse.x = ((event.clientX-canvasOffset.left)/canvas.clientWidth) * 2 - 1;
|
||||
this.mouse.y = -((event.clientY-canvasOffset.top)/canvas.clientHeight) * 2 + 1;
|
||||
this.mouse.z = 0;
|
||||
}
|
||||
|
||||
@@ -174,22 +168,23 @@ export class RectsComponent implements OnChanges, OnDestroy {
|
||||
if (this.canvasSubscription) {
|
||||
this.canvasSubscription.unsubscribe();
|
||||
}
|
||||
this.canvasService.initialise();
|
||||
const canvas = document.getElementById("rects-canvas") as HTMLCanvasElement;
|
||||
this.canvasGraphics.initialise(canvas);
|
||||
this.canvasSubscription = this.drawRectsInterval.subscribe(() => {
|
||||
this.updateVariablesBeforeRefresh();
|
||||
this.canvasService.refreshCanvas();
|
||||
this.canvasGraphics.refreshCanvas();
|
||||
});
|
||||
}
|
||||
|
||||
updateVariablesBeforeRefresh() {
|
||||
this.canvasService.updateRects(this.rects);
|
||||
this.canvasGraphics.updateRects(this.rects);
|
||||
const biggestX = Math.max(...this.rects.map(rect => rect.topLeft.x + rect.width/2));
|
||||
this.canvasService.updateIsLandscape(biggestX > this.s({x: this.boundsWidth, y:this.boundsHeight}).x/2);
|
||||
this.canvasGraphics.updateIsLandscape(biggestX > this.s({x: this.boundsWidth, y:this.boundsHeight}).x/2);
|
||||
}
|
||||
|
||||
onChangeView(visible: boolean) {
|
||||
this.canvasService.updateVisibleView(visible);
|
||||
this.canvasService.clearLabelElements();
|
||||
this.canvasGraphics.updateVisibleView(visible);
|
||||
this.canvasGraphics.clearLabelElements();
|
||||
}
|
||||
|
||||
scaleRects() {
|
||||
@@ -209,20 +204,17 @@ export class RectsComponent implements OnChanges, OnDestroy {
|
||||
}
|
||||
|
||||
computeBounds(): any {
|
||||
if (this.bounds) {
|
||||
return this.bounds;
|
||||
}
|
||||
this.boundsWidth = Math.max(...this.rects.map((rect) => {
|
||||
const mat = this.getMatrix(rect);
|
||||
if (mat) {
|
||||
return MatrixUtils.transformRect(mat, rect).width;
|
||||
return RectsUtils.transformRect(mat, rect).width;
|
||||
} else {
|
||||
return rect.width;
|
||||
}}));
|
||||
this.boundsHeight = Math.max(...this.rects.map((rect) => {
|
||||
const mat = this.getMatrix(rect);
|
||||
if (mat) {
|
||||
return MatrixUtils.transformRect(mat, rect).height;
|
||||
return RectsUtils.transformRect(mat, rect).height;
|
||||
} else {
|
||||
return rect.height;
|
||||
}}));
|
||||
@@ -245,9 +237,9 @@ export class RectsComponent implements OnChanges, OnDestroy {
|
||||
s(sourceCoordinates: Point) {
|
||||
let scale;
|
||||
if (this.boundsWidth < this.boundsHeight) {
|
||||
scale = this.canvasService.cameraHalfHeight*2 * 0.6 / this.boundsHeight;
|
||||
scale = this.canvasGraphics.cameraHalfHeight*2 * 0.6 / this.boundsHeight;
|
||||
} else {
|
||||
scale = this.canvasService.cameraHalfWidth*2 * 0.6 / this.boundsWidth;
|
||||
scale = this.canvasGraphics.cameraHalfWidth*2 * 0.6 / this.boundsWidth;
|
||||
}
|
||||
return {
|
||||
x: sourceCoordinates.x * scale,
|
||||
@@ -268,26 +260,27 @@ export class RectsComponent implements OnChanges, OnDestroy {
|
||||
}
|
||||
|
||||
visibleView() {
|
||||
return this.canvasService.getVisibleView();
|
||||
return this.canvasGraphics.getVisibleView();
|
||||
}
|
||||
|
||||
getLayerSeparation() {
|
||||
return this.canvasService.getLayerSeparation();
|
||||
return this.canvasGraphics.getLayerSeparation();
|
||||
}
|
||||
|
||||
xyCameraPos() {
|
||||
return this.canvasService.getXyCameraPos();
|
||||
return this.canvasGraphics.getXyCameraPos();
|
||||
}
|
||||
|
||||
showVirtualDisplays() {
|
||||
return this.canvasService.getShowVirtualDisplays();
|
||||
return this.canvasGraphics.getShowVirtualDisplays();
|
||||
}
|
||||
|
||||
canvasGraphics: CanvasGraphics;
|
||||
private readonly _60fpsInterval = 16.66666666666667;
|
||||
private drawRectsInterval = interval(this._60fpsInterval);
|
||||
private boundsWidth = 0;
|
||||
private boundsHeight = 0;
|
||||
private displayRects: Rectangle[];
|
||||
private canvasSubscription: Subscription;
|
||||
private displayRects!: Rectangle[];
|
||||
private canvasSubscription?: Subscription;
|
||||
private mouse = new THREE.Vector3(0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { MatrixUtils } from "./matrix_utils";
|
||||
import { RectsUtils } from "./rects_utils";
|
||||
|
||||
describe("MatrixUtils", () => {
|
||||
describe("RectsUtils", () => {
|
||||
it("transforms rect", () => {
|
||||
const transform = {
|
||||
matrix: {
|
||||
@@ -54,6 +54,6 @@ describe("MatrixUtils", () => {
|
||||
stackId: 0,
|
||||
isVirtual: undefined
|
||||
};
|
||||
expect(MatrixUtils.transformRect(rect.transform.matrix, rect)).toEqual(expected);
|
||||
expect(RectsUtils.transformRect(rect.transform.matrix, rect)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@@ -13,9 +13,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Point, Rectangle, RectMatrix, RectTransform } from "ui_data/ui_data_surface_flinger";
|
||||
import { Point, Rectangle, RectMatrix, RectTransform } from "viewers/viewer_surface_flinger/ui_data";
|
||||
|
||||
export const MatrixUtils = {
|
||||
export const RectsUtils = {
|
||||
multiplyMatrix(matrix:any, corner: Point): Point {
|
||||
if (!matrix) return corner;
|
||||
// |dsdx dsdy tx| | x | |x*dsdx + y*dsdy + tx|
|
||||
@@ -19,6 +19,7 @@ interface Viewer {
|
||||
//TODO: add TraceEntry data type
|
||||
notifyCurrentTraceEntries(entries: Map<TraceType, any>): void;
|
||||
getView(): HTMLElement;
|
||||
getTitle(): string;
|
||||
getDependencies(): TraceType[];
|
||||
}
|
||||
|
||||
|
||||
@@ -13,30 +13,28 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Rectangle, RectMatrix, UiDataSurfaceFlinger } from "ui_data/ui_data_surface_flinger";
|
||||
import { Presenter } from "./presenter";
|
||||
import { UiDataCallbackType } from "./presenter";
|
||||
import { Rectangle, RectMatrix, RectTransform, UiData } from "viewers/viewer_surface_flinger/ui_data";
|
||||
import { TraceType } from "common/trace/trace_type";
|
||||
|
||||
class PresenterSurfaceFlinger extends Presenter {
|
||||
constructor(uiDataCallback: UiDataCallbackType) {
|
||||
super(uiDataCallback);
|
||||
this.uiDataCallback = uiDataCallback;
|
||||
this.uiData = new UiDataSurfaceFlinger("Initial UI data");
|
||||
this.uiDataCallback(this.uiData);
|
||||
type NotifyViewCallbackType = (uiData: UiData) => void;
|
||||
|
||||
class Presenter {
|
||||
constructor(notifyViewCallback: NotifyViewCallbackType) {
|
||||
this.notifyViewCallback = notifyViewCallback;
|
||||
this.uiData = new UiData("Initial UI data");
|
||||
this.notifyViewCallback(this.uiData);
|
||||
}
|
||||
|
||||
updateHighlightedRect(event: any) {
|
||||
updateHighlightedRect(event: CustomEvent) {
|
||||
this.highlighted = event.detail.layerId;
|
||||
this.uiData.highlighted = this.highlighted;
|
||||
console.log("changed highlighted rect: ", this.uiData.highlighted);
|
||||
this.uiDataCallback(this.uiData);
|
||||
this.notifyViewCallback(this.uiData);
|
||||
}
|
||||
|
||||
override notifyCurrentTraceEntries(entries: Map<TraceType, any>) {
|
||||
notifyCurrentTraceEntries(entries: Map<TraceType, any>) {
|
||||
const entry = entries.get(TraceType.SURFACE_FLINGER);
|
||||
this.uiData = new UiDataSurfaceFlinger("New surface flinger ui data");
|
||||
this.uiData.rects = [];
|
||||
this.uiData = new UiData("New surface flinger ui data");
|
||||
const displayRects = entry.displays.map((display: any) => {
|
||||
const rect = display.layerStackSpace;
|
||||
rect.label = display.name;
|
||||
@@ -45,13 +43,14 @@ class PresenterSurfaceFlinger extends Presenter {
|
||||
rect.isDisplay = true;
|
||||
rect.isVirtual = display.isVirtual;
|
||||
return rect;
|
||||
});
|
||||
}) ?? [];
|
||||
this.uiData.highlighted = this.highlighted;
|
||||
this.rectToUiData(entry.rects.concat(displayRects));
|
||||
this.uiDataCallback(this.uiData);
|
||||
this.uiData.rects = this.rectsToUiData(entry.rects.concat(displayRects));
|
||||
this.notifyViewCallback(this.uiData);
|
||||
}
|
||||
|
||||
rectToUiData(rects: any[]) {
|
||||
rectsToUiData(rects: any[]): Rectangle[] {
|
||||
const uiRects: Rectangle[] = [];
|
||||
rects.forEach((rect: any) => {
|
||||
let t = null;
|
||||
if (rect.transform && rect.transform.matrix) {
|
||||
@@ -59,7 +58,7 @@ class PresenterSurfaceFlinger extends Presenter {
|
||||
} else if (rect.transform) {
|
||||
t = rect.transform;
|
||||
}
|
||||
let transform = null;
|
||||
let transform: RectTransform | null = null;
|
||||
if (t !== null) {
|
||||
const matrix: RectMatrix = {
|
||||
dsdx: t.dsdx,
|
||||
@@ -96,13 +95,14 @@ class PresenterSurfaceFlinger extends Presenter {
|
||||
stackId: rect.stackId ?? rect.ref.stackId,
|
||||
isVirtual: rect.isVirtual
|
||||
};
|
||||
this.uiData.rects?.push(newRect);
|
||||
uiRects.push(newRect);
|
||||
});
|
||||
return uiRects;
|
||||
}
|
||||
|
||||
override readonly uiDataCallback: UiDataCallbackType;
|
||||
override uiData: UiDataSurfaceFlinger;
|
||||
private readonly notifyViewCallback: NotifyViewCallbackType;
|
||||
private uiData: UiData;
|
||||
private highlighted = "";
|
||||
}
|
||||
|
||||
export {PresenterSurfaceFlinger};
|
||||
export {Presenter};
|
||||
@@ -13,9 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { UiData } from "./ui_data";
|
||||
|
||||
class UiDataSurfaceFlinger extends UiData {
|
||||
class UiData {
|
||||
constructor(public text: string) {
|
||||
console.log(text);
|
||||
}
|
||||
rects?: Rectangle[] = [];
|
||||
highlighted?: string = "";
|
||||
}
|
||||
@@ -59,4 +60,4 @@ export interface RectMatrix {
|
||||
ty: number;
|
||||
}
|
||||
|
||||
export {UiDataSurfaceFlinger};
|
||||
export {UiData};
|
||||
@@ -22,8 +22,7 @@ import { RectsComponent } from "viewers/rects.component";
|
||||
import { MatIconModule } from "@angular/material/icon";
|
||||
import { MatCardModule } from "@angular/material/card";
|
||||
import { ComponentFixtureAutoDetect } from "@angular/core/testing";
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from "@angular/core";
|
||||
import { CanvasService } from "viewers/canvas.service";
|
||||
import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
|
||||
|
||||
describe("ViewerSurfaceFlingerComponent", () => {
|
||||
let fixture: ComponentFixture<ViewerSurfaceFlingerComponent>;
|
||||
@@ -33,7 +32,6 @@ describe("ViewerSurfaceFlingerComponent", () => {
|
||||
beforeAll(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
providers: [
|
||||
CanvasService,
|
||||
{ provide: ComponentFixtureAutoDetect, useValue: true }
|
||||
],
|
||||
imports: [
|
||||
@@ -46,7 +44,7 @@ describe("ViewerSurfaceFlingerComponent", () => {
|
||||
PropertiesComponent,
|
||||
RectsComponent
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
Component,
|
||||
Input
|
||||
} from "@angular/core";
|
||||
import { UiDataSurfaceFlinger } from "../../ui_data/ui_data_surface_flinger";
|
||||
import { UiData } from "./ui_data";
|
||||
import { TRACE_INFO } from "app/trace_info";
|
||||
import { TraceType } from "common/trace/trace_type";
|
||||
|
||||
@@ -29,7 +29,6 @@ import { TraceType } from "common/trace/trace_type";
|
||||
<rects-view
|
||||
[rects]="inputData?.rects ?? []"
|
||||
[highlighted]="inputData?.highlighted ?? ''"
|
||||
[id]="TraceType.SURFACE_FLINGER"
|
||||
class="rects-view"
|
||||
></rects-view>
|
||||
</mat-card>
|
||||
@@ -54,7 +53,7 @@ import { TraceType } from "common/trace/trace_type";
|
||||
})
|
||||
export class ViewerSurfaceFlingerComponent {
|
||||
@Input()
|
||||
inputData?: UiDataSurfaceFlinger;
|
||||
inputData?: UiData;
|
||||
|
||||
TRACE_INFO = TRACE_INFO;
|
||||
TraceType = TraceType;
|
||||
|
||||
@@ -15,16 +15,16 @@
|
||||
*/
|
||||
import {TraceType} from "common/trace/trace_type";
|
||||
import {Viewer} from "viewers/viewer";
|
||||
import {PresenterSurfaceFlinger} from "../../presenters/presenter_surface_flinger";
|
||||
import {UiDataSurfaceFlinger} from "../../ui_data/ui_data_surface_flinger";
|
||||
import {Presenter} from "./presenter";
|
||||
import {UiData} from "./ui_data";
|
||||
|
||||
class ViewerSurfaceFlinger implements Viewer {
|
||||
constructor() {
|
||||
this.view = document.createElement("viewer-surface-flinger");
|
||||
this.presenter = new PresenterSurfaceFlinger((uiData: UiDataSurfaceFlinger) => {
|
||||
this.presenter = new Presenter((uiData: UiData) => {
|
||||
(this.view as any).inputData = uiData;
|
||||
});
|
||||
this.view.addEventListener("highlightedChange", (event) => this.presenter.updateHighlightedRect(event));
|
||||
this.view.addEventListener("highlightedChange", (event) => this.presenter.updateHighlightedRect((event as CustomEvent)));
|
||||
}
|
||||
|
||||
public notifyCurrentTraceEntries(entries: Map<TraceType, any>): void {
|
||||
@@ -35,13 +35,17 @@ class ViewerSurfaceFlinger implements Viewer {
|
||||
return this.view;
|
||||
}
|
||||
|
||||
public getTitle(): string {
|
||||
return "Surface Flinger";
|
||||
}
|
||||
|
||||
public getDependencies(): TraceType[] {
|
||||
return ViewerSurfaceFlinger.DEPENDENCIES;
|
||||
}
|
||||
|
||||
public static readonly DEPENDENCIES: TraceType[] = [TraceType.SURFACE_FLINGER];
|
||||
private view: HTMLElement;
|
||||
private presenter: PresenterSurfaceFlinger;
|
||||
private presenter: Presenter;
|
||||
}
|
||||
|
||||
export {ViewerSurfaceFlinger};
|
||||
|
||||
@@ -14,31 +14,31 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {TraceType} from "common/trace/trace_type";
|
||||
import {UiData} from "../ui_data/ui_data";
|
||||
import {UiData} from "./ui_data";
|
||||
|
||||
type UiDataCallbackType = (uiData: UiData) => void;
|
||||
type NotifyViewCallbackType = (uiData: UiData) => void;
|
||||
|
||||
class Presenter {
|
||||
constructor(uiDataCallback: UiDataCallbackType) {
|
||||
this.uiDataCallback = uiDataCallback;
|
||||
constructor(notifyViewCallback: NotifyViewCallbackType) {
|
||||
this.notifyViewCallback = notifyViewCallback;
|
||||
this.uiData = new UiData("Initial UI data");
|
||||
this.uiDataCallback(this.uiData);
|
||||
this.notifyViewCallback(this.uiData);
|
||||
}
|
||||
|
||||
public notifyCurrentTraceEntries(entries: Map<TraceType, any>) {
|
||||
this.uiData = new UiData("UI data selected by user on time scrub");
|
||||
this.uiDataCallback(this.uiData);
|
||||
this.notifyViewCallback(this.uiData);
|
||||
}
|
||||
|
||||
public notifyUiEvent() {
|
||||
const oldUiDataText = this.uiData ? this.uiData.text : "";
|
||||
this.uiData = new UiData(oldUiDataText);
|
||||
this.uiData.text += " | UI data updated because of UI event";
|
||||
this.uiDataCallback(this.uiData!);
|
||||
this.notifyViewCallback(this.uiData!);
|
||||
}
|
||||
|
||||
readonly uiDataCallback: UiDataCallbackType;
|
||||
readonly notifyViewCallback: NotifyViewCallbackType;
|
||||
uiData?: UiData;
|
||||
}
|
||||
|
||||
export {Presenter, UiDataCallbackType};
|
||||
export {Presenter};
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
import {ComponentFixture, TestBed} from "@angular/core/testing";
|
||||
import {ViewerWindowManagerComponent} from "./viewer_window_manager.component";
|
||||
import {UiData} from "../../ui_data/ui_data";
|
||||
import {UiData} from "./ui_data";
|
||||
|
||||
describe("ViewerWindowManagerComponent", () => {
|
||||
let fixture: ComponentFixture<ViewerWindowManagerComponent>;
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
Input,
|
||||
Output
|
||||
} from "@angular/core";
|
||||
import {UiData} from "../../ui_data/ui_data";
|
||||
import {UiData} from "./ui_data";
|
||||
|
||||
@Component({
|
||||
selector: "viewer-window-manager",
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
import {TraceType} from "common/trace/trace_type";
|
||||
import {Viewer} from "viewers/viewer";
|
||||
import {Presenter} from "../../presenters/presenter";
|
||||
import {UiData} from "../../ui_data/ui_data";
|
||||
import {Presenter} from "./presenter";
|
||||
import {UiData} from "./ui_data";
|
||||
|
||||
class ViewerWindowManager implements Viewer {
|
||||
constructor() {
|
||||
@@ -27,6 +27,10 @@ class ViewerWindowManager implements Viewer {
|
||||
this.view.addEventListener("outputEvent", () => this.presenter.notifyUiEvent());
|
||||
}
|
||||
|
||||
public getTitle() {
|
||||
return "Window Manager";
|
||||
}
|
||||
|
||||
public notifyCurrentTraceEntries(entries: Map<TraceType, any>): void {
|
||||
this.presenter.notifyCurrentTraceEntries(entries);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
"allowJs": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
@@ -17,7 +16,6 @@
|
||||
"declaration": false,
|
||||
"downlevelIteration": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"target": "es2020",
|
||||
|
||||
Reference in New Issue
Block a user