• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
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 */
15
16import {BaseElement, element} from "../../../../base-ui/BaseElement.js";
17import {LitTabs} from "../../../../base-ui/tabs/lit-tabs.js";
18import {CpuStruct} from "../../../bean/CpuStruct.js";
19import {LitTabpane} from "../../../../base-ui/tabs/lit-tabpane.js";
20import {BoxJumpParam, SelectionParam} from "../../../bean/BoxSelection.js";
21import {TabPaneCurrentSelection} from "../sheet/TabPaneCurrentSelection.js";
22import {FuncStruct} from "../../../bean/FuncStruct.js";
23import {ProcessMemStruct} from "../../../bean/ProcessMemStruct.js";
24import {ThreadStruct} from "../../../bean/ThreadStruct.js";
25import {TabPaneFlag} from "../timer-shaft/TabPaneFlag.js";
26import {Flag} from "../timer-shaft/Flag.js";
27import {WakeupBean} from "../../../bean/WakeupBean.js";
28import {LitIcon} from "../../../../base-ui/icon/LitIcon.js";
29import {CpuFreqStruct} from "../../../bean/CpuFreqStruct.js";
30import {tabConfig} from "./TraceSheetConfig.js";
31import {TabPaneBoxChild} from "../sheet/cpu/TabPaneBoxChild.js";
32import {CpuStateStruct} from "../../../database/ui-worker/ProcedureWorkerCpuState.js";
33import {SpFreqChart} from "../../chart/SpFreqChart.js";
34import {CpuFreqLimitsStruct} from "../../../database/ui-worker/ProcedureWorkerCpuFreqLimits.js";
35
36
37@element("trace-sheet")
38export class TraceSheet extends BaseElement {
39    private litTabs: LitTabs | undefined | null
40    private nav: HTMLDivElement | undefined | null
41    private selection: SelectionParam | undefined | null;
42    private currentPaneID: string = "current-selection";
43
44    static get observedAttributes() {
45        return ['mode'];
46    }
47
48    buildTabs(litTabs: LitTabs | undefined | null) {
49        Reflect.ownKeys(tabConfig).forEach((key, index) => {
50            let pane = new LitTabpane();
51            pane.id = key.toString();
52            pane.className = "tabHeight";
53            pane.tab = tabConfig[key].title;
54            pane.hidden = true;
55            pane.key = `${tabConfig[key].key || index}`;
56            let cls = tabConfig[key].type;
57            let node = new cls();
58            pane.append(node)
59            litTabs!.append(pane);
60        })
61    }
62
63    displayTab<T>(...names: string[]): T {
64        this.setAttribute("mode", "max")
65        this.shadowRoot?.querySelectorAll<LitTabpane>("#tabs lit-tabpane").forEach(it => it.hidden = !names.some(k => k === it.id))
66        let litTabpane = this.shadowRoot?.querySelector<LitTabpane>(`#tabs lit-tabpane[id='${names[0]}']`);
67        this.shadowRoot?.querySelector<LitTabs>("#tabs")?.activePane(litTabpane!.key)
68        return litTabpane!.children.item(0) as unknown as T;
69    }
70
71    getComponentByID<T>(id: string): T {
72        return (this.getPaneByID(id)!.children.item(0) as unknown as T);
73    }
74
75    getPaneByID(id: string): LitTabpane {
76        return this.shadowRoot!.querySelector(`#${id}`)!;
77    }
78
79    initElements(): void {
80        this.litTabs = this.shadowRoot?.querySelector("#tabs");
81        this.buildTabs(this.litTabs);
82        let minBtn = this.shadowRoot?.querySelector("#min-btn");
83        minBtn?.addEventListener('click', () => {
84        });
85        this.litTabs!.onTabClick = (e: any) => this.loadTabPaneData(e.detail.key)
86        this.litTabs!.addEventListener("close-handler", () => {
87            Reflect.ownKeys(tabConfig).reverse().forEach(id => {
88                let element = tabConfig[id];
89                let pane = this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`);
90                if (element.require) {
91                    pane!.hidden = !element.require(this.selection);
92                } else {
93                    pane!.hidden = true;
94                }
95            })
96            this.litTabs?.activeByKey(`${this.getPaneByID(this.currentPaneID).key}`);
97        })
98        this.getComponentByID<any>("box-spt")!.addEventListener("row-click", this.rowClickHandler.bind(this));
99        this.getComponentByID<any>("box-pts")!.addEventListener("row-click", this.rowClickHandler.bind(this));
100        this.getComponentByID<any>("box-cs")!.addEventListener("row-click", this.rowClickHandler.bind(this));
101        this.getComponentByID<any>("box-ts")!.addEventListener("row-click", this.rowClickHandler.bind(this));
102        this.getComponentByID<any>("box-native-statstics")!.addEventListener("row-click", (e: any) => {
103            this.selection!.statisticsSelectData = e.detail
104            let pane = this.getPaneByID("box-native-memory");
105            this.litTabs?.activeByKey(pane.key);
106            (pane.children.item(0) as any)!.fromStastics(this.selection)
107        });
108        this.getComponentByID<any>("box-virtual-memory-statistics")!.addEventListener("row-click", (e: any) => {
109            this.selection!.fileSystemVMData = {path:e.detail.path}
110            let pane = this.getPaneByID("box-vm-events");
111            this.litTabs?.activeByKey(pane.key);
112            if (e.detail.path) {
113                (pane.children.item(0) as any)!.fromStastics(this.selection)
114            }
115        });
116    }
117
118    connectedCallback() {
119        this.nav = this.shadowRoot?.querySelector("#tabs")?.shadowRoot?.querySelector('.tab-nav-container')
120        let tabs: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#tabs')
121        let navRoot: HTMLDivElement | null | undefined = this.shadowRoot?.querySelector("#tabs")?.shadowRoot?.querySelector('.nav-root')
122        let search: HTMLDivElement | undefined | null = document.querySelector("body > sp-application")?.shadowRoot?.querySelector("div > div.search-container")
123        let timerShaft: HTMLDivElement | undefined | null = this.parentElement?.querySelector(".timer-shaft")
124        let spacer: HTMLDivElement | undefined | null = this.parentElement?.querySelector(".spacer")
125        let borderTop: number = 1;
126        let initialHeight = {tabs: `calc(30vh + 39px)`, node: "30vh"};
127        this.nav!.onmousedown = (event) => {
128            (window as any).isSheetMove = true;
129            let litTabpane: NodeListOf<HTMLDivElement> | undefined | null = this.shadowRoot?.querySelectorAll("#tabs > lit-tabpane")
130            let preY = event.pageY;
131            let preHeight = tabs!.offsetHeight;
132            document.onmousemove = function (event) {
133                let moveY: number = preHeight - (event.pageY - preY)
134                litTabpane!.forEach((node: HTMLDivElement) => {
135                    if (navRoot!.offsetHeight <= moveY && (search!.offsetHeight + timerShaft!.offsetHeight + borderTop + spacer!.offsetHeight) <= (window.innerHeight - moveY)) {
136                        tabs!.style.height = moveY + "px"
137                        node!.style.height = (moveY - navRoot!.offsetHeight) + "px"
138                        tabsPackUp!.name = "down"
139                    } else if (navRoot!.offsetHeight >= moveY) {
140                        tabs!.style.height = navRoot!.offsetHeight + "px"
141                        node!.style.height = "0px"
142                        tabsPackUp!.name = "up"
143                    } else if ((search!.offsetHeight + timerShaft!.offsetHeight + borderTop + spacer!.offsetHeight) >= (window.innerHeight - moveY)) {
144                        tabs!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - borderTop - spacer!.offsetHeight) + "px"
145                        node!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - navRoot!.offsetHeight - borderTop - spacer!.offsetHeight) + "px"
146                        tabsPackUp!.name = "down"
147                    }
148                })
149            }
150            document.onmouseup = function () {
151                (window as any).isSheetMove = false;
152                litTabpane!.forEach((node: HTMLDivElement) => {
153                    if (node!.style.height !== "0px" && tabs!.style.height != "") {
154                        initialHeight.node = node!.style.height;
155                        initialHeight.tabs = tabs!.style.height;
156                    }
157                })
158                this.onmousemove = null;
159                this.onmouseup = null;
160            }
161        }
162        let tabsOpenUp: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>("#tabs > div > lit-icon:nth-child(1)")
163        let tabsPackUp: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>("#tabs > div > lit-icon:nth-child(2)")
164        tabsOpenUp!.onclick = () => {
165            tabs!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - borderTop) + "px"
166            let litTabpane: NodeListOf<HTMLDivElement> | undefined | null = this.shadowRoot?.querySelectorAll("#tabs > lit-tabpane")
167            litTabpane!.forEach((node: HTMLDivElement) => {
168                node!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - navRoot!.offsetHeight - borderTop) + "px"
169                initialHeight.node = node!.style.height;
170            })
171            initialHeight.tabs = tabs!.style.height;
172            tabsPackUp!.name = "down"
173        }
174        tabsPackUp!.onclick = () => {
175            let litTabpane: NodeListOf<HTMLDivElement> | undefined | null = this.shadowRoot?.querySelectorAll("#tabs > lit-tabpane")
176            if (tabsPackUp!.name == "down") {
177                tabs!.style.height = navRoot!.offsetHeight + "px"
178                litTabpane!.forEach((node: HTMLDivElement) => node!.style.height = "0px")
179                tabsPackUp!.name = "up";
180                (window as any).isPackUpTable = true;
181            } else {
182                tabsPackUp!.name = "down"
183                tabs!.style.height = initialHeight.tabs;
184                litTabpane!.forEach((node: HTMLDivElement) => node!.style.height = initialHeight.node)
185            }
186        }
187    }
188
189    initHtml(): string {
190        return `
191            <style>
192                :host([mode='hidden']){
193                    display: none;
194                }
195                :host{
196                    display: block;
197                    background-color: rebeccapurple;
198                }
199                .tabHeight{
200                    height: 30vh;
201                    background-color: var(--dark-background,#FFFFFF);
202                }
203            </style>
204            <div style="border-top: 1px solid var(--dark-border1,#D5D5D5);">
205                <lit-tabs id="tabs" position="top-left" activekey="1" mode="card" >
206                    <div slot="right" style="margin: 0 10px; color: var(--dark-icon,#606060);display: flex;align-items: center;">
207                        <lit-icon id="max-btn" name="vertical-align-top" style="font-weight: bold;cursor: pointer;margin-right: 5px" size="20">
208                        </lit-icon>
209                        <lit-icon id="min-btn" name="down" style="font-weight: bold;cursor: pointer;" size="20">
210                        </lit-icon>
211                    </div>
212                </lit-tabs>
213            </div>`;
214    }
215
216    displayThreadData = (data: ThreadStruct, scrollCallback: ((e: ThreadStruct) => void) | undefined, scrollWakeUp: (d: any) => void | undefined) =>
217        this.displayTab<TabPaneCurrentSelection>("current-selection").setThreadData(data, scrollCallback, scrollWakeUp)
218    displayMemData = (data: ProcessMemStruct) =>
219        this.displayTab<TabPaneCurrentSelection>("current-selection").setMemData(data);
220    displayFuncData = (data: FuncStruct, scrollCallback: Function) =>
221        this.displayTab<TabPaneCurrentSelection>("current-selection").setFunctionData(data, scrollCallback);
222    displayCpuData = (data: CpuStruct, callback: ((data: WakeupBean | null) => void) | undefined = undefined, scrollCallback?: (data: CpuStruct) => void) =>
223        this.displayTab<TabPaneCurrentSelection>("current-selection").setCpuData(data, callback, scrollCallback);
224    displayFlagData = (flagObj: Flag) => this.displayTab<TabPaneFlag>("box-flag").setFlagObj(flagObj);
225    displayFreqData = () => this.displayTab<TabPaneCurrentSelection>("box-freq").data = CpuFreqStruct.selectCpuFreqStruct;
226    displayCpuStateData = () => this.displayTab<TabPaneCurrentSelection>("cpu-state-click").data = SpFreqChart.selectStateStruct;
227    displayFreqLimitData = () => this.displayTab<TabPaneCurrentSelection>("box-freq-limit").data = CpuFreqLimitsStruct.selectCpuFreqLimitsStruct;
228
229    rangeSelect(selection: SelectionParam): boolean {
230        this.selection = selection;
231        Reflect.ownKeys(tabConfig).reverse().forEach(id => {
232            let element = tabConfig[id];
233            if (element.require) {
234                if (element.require(selection)) {
235                    let pane = this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`);
236                    pane!.hidden = false;
237                } else {
238                    this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`)!.hidden = true;
239                }
240            } else {
241                this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`)!.hidden = true;
242            }
243        })
244        let firstPane = this.shadowRoot!.querySelector<LitTabpane>(`lit-tabpane[hidden='false']`);
245        if (firstPane) {
246            this.litTabs?.activeByKey(firstPane.key)
247            this.loadTabPaneData(firstPane.key)
248            this.setAttribute("mode", "max")
249            return true;
250        } else {
251            this.setAttribute("mode", "hidden")
252            return false;
253        }
254    }
255
256    loadTabPaneData(key: string) {
257        let component: any = this.shadowRoot?.querySelector<LitTabpane>(`#tabs lit-tabpane[key='${key}']`)?.children.item(0);
258        if (component) {
259            component.data = this.selection;
260        }
261    }
262
263    rowClickHandler(e: any) {
264        this.currentPaneID = e.target.parentElement.id
265        this.shadowRoot!.querySelectorAll<LitTabpane>(`lit-tabpane`)
266            .forEach(it => it.id != this.currentPaneID ? (it.hidden = true) : (it.hidden = false));
267        let pane = this.getPaneByID("box-cpu-child");
268        pane.closeable = true;
269        pane.hidden = false;
270        this.litTabs!.activeByKey(pane.key)
271        pane.tab = e.detail.title
272        let param = new BoxJumpParam();
273        param.leftNs = this.selection!.leftNs;
274        param.rightNs = this.selection!.rightNs;
275        param.state = e.detail.state;
276        param.threadId = e.detail.threadId;
277        param.processId = e.detail.processId;
278        (pane.children.item(0) as TabPaneBoxChild).data = param;
279    }
280}
281