• 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 */
15import {BaseElement, element} from "../../../../base-ui/BaseElement.js";
16import {TraceRowObject} from "./TraceRowObject.js";
17import {TraceRow} from "./TraceRow.js";
18import {log} from "../../../../log/Log.js";
19
20@element("trace-row-recycler-view")
21export class TraceRowRecyclerView extends BaseElement {
22    private recycler: boolean = true;
23    private gasketEL: HTMLDivElement | null | undefined;
24    private container: HTMLDivElement | null | undefined;
25    private visibleRowsCount: number = 0;
26    private visibleObjects: TraceRowObject<any>[] = [];
27    private totalHeight: number = 0;
28
29    private _dataSource: Array<TraceRowObject<any>> = [];
30    private _renderType: string = 'div';
31
32    get dataSource(): Array<TraceRowObject<any>> {
33        return this._dataSource;
34    }
35
36    set dataSource(value: Array<TraceRowObject<any>>) {
37        log("dataSource TraceRowObject size :" +  value.length);
38        this._dataSource = value;
39        this.measureHeight();
40        this.initUI();
41        let els = [...(this.shadowRoot!.querySelectorAll<TraceRow<any>>(".recycler-cell"))];
42        for (let i = 0; i < els.length; i++) {
43            this.refreshRow(els[i], this.visibleObjects[i]);
44        }
45    }
46
47    get renderType(): string {
48        return this._renderType;
49    }
50
51    set renderType(value: string) {
52        this._renderType = value;
53    }
54
55    refreshRow(el: TraceRow<any>, obj: TraceRowObject<any>) {
56        if (!obj) {
57            return;
58        }
59        el.obj = obj;
60        el.folder = obj.folder;
61        el.style.top = `${obj.top}px`;
62        el.name = obj.name || '';
63        if (obj.children) {
64            el.setAttribute("children", ``);
65        } else {
66            el.removeAttribute("children");
67        }
68        el.style.visibility = 'visible';
69        el.rowId = obj.rowId
70        el.rowType = obj.rowType
71        el.rowParentId = obj.rowParentId
72        el.expansion = obj.expansion
73        el.rowHidden = obj.rowHidden
74        el.setAttribute("height", `${obj.rowHeight}`);
75        requestAnimationFrame(() => {
76        })
77    }
78
79    initElements(): void {
80        this.container = this.shadowRoot?.querySelector<HTMLDivElement>(".container");
81        this.gasketEL = this.shadowRoot?.querySelector<HTMLDivElement>(".gasket");
82        let els: Array<TraceRow<any>> | undefined | null;
83        this.container!.onscroll = (ev) => {
84            let top = this.container!.scrollTop;
85            let skip = 0;
86            for (let i = 0; i < this.visibleObjects.length; i++) {
87                if (this.visibleObjects[i].top >= top) {
88                    skip = this.visibleObjects[i].rowIndex - 1;
89                    break;
90                }
91            }
92            if (skip < 0) skip = 0;
93            if (!els) els = [...(this.shadowRoot!.querySelectorAll<TraceRow<any>>(".recycler-cell"))];
94            for (let i = 0; i < els.length; i++) {
95                let obj = this.visibleObjects[i + skip];
96                this.refreshRow(els[i], obj);
97            }
98        }
99    }
100
101
102    measureHeight() {
103        this.visibleObjects = this.dataSource.filter(it => !it.rowHidden);
104        this.totalHeight = this.visibleObjects.map((it) => it.rowHeight).reduce((a, b) => a + b);
105        let totalHeight = 0;
106        for (let i = 0; i < this.visibleObjects.length; i++) {
107            this.visibleObjects[i].top = totalHeight;
108            this.visibleObjects[i].rowIndex = i;
109            totalHeight += this.visibleObjects[i].rowHeight;
110            this.visibleObjects[i].preObject = i == 0 ? null : this.visibleObjects[i - 1];
111            this.visibleObjects[i].nextObject = i == this.visibleObjects.length - 1 ? null : this.visibleObjects[i + 1];
112        }
113        this.gasketEL && (this.gasketEL.style.height = `${this.totalHeight}px`);
114    }
115
116    initUI() {
117        this.visibleRowsCount = Math.ceil(this.clientHeight / 40);
118        if (this.visibleRowsCount >= this.visibleObjects.length) {
119            this.visibleRowsCount = this.visibleObjects.length;
120        }
121        if (!this.recycler) this.visibleRowsCount = this.dataSource.length;
122        for (let i = 0; i <= this.visibleRowsCount; i++) {
123            let el = new TraceRow<any>({canvasNumber: 1, alpha: true, contextId: '2d', isOffScreen: true});
124            el.className = "recycler-cell"
125            this.container?.appendChild(el);
126            el.addEventListener('expansion-change', (ev: any) => {
127                el.obj!.expansion = ev.detail.expansion;
128                for (let j = 0; j < this.dataSource.length; j++) {
129                    if (this.dataSource[j].rowParentId == ev.detail.rowId) {
130                        this.dataSource[j].rowHidden = !ev.detail.expansion;
131                    }
132                }
133                this.measureHeight();
134                let els = [...(this.shadowRoot!.querySelectorAll<TraceRow<any>>(".recycler-cell"))];
135                let top = this.container!.scrollTop;
136                let skip = 0;
137                for (let i = 0; i < this.visibleObjects.length; i++) {
138                    if (this.visibleObjects[i].top >= top) {
139                        skip = this.visibleObjects[i].rowIndex - 1;
140                        break;
141                    }
142                }
143                if (skip < 0) skip = 0;
144                for (let i = 0; i < els.length; i++) {
145                    let obj = this.visibleObjects[i + skip];
146                    this.refreshRow(els[i], obj);
147                }
148            })
149        }
150    }
151
152    initHtml(): string {
153        return `
154        <style>
155        :host{
156            width:100%;
157            height:100%;
158            display: block;
159            position:relative;
160        }
161        .container{
162            width:100%;
163            height:100%;
164            overflow: auto;
165            position: absolute;
166            display: block;
167        }
168        .gasket{
169            width:100%;
170            height:auto;
171            top: 0;
172            left: 0;
173            right:0;
174            bottom:0;
175            visibility: hidden;
176        }
177        .recycler-cell{
178            position: absolute;
179            width:100%;
180            visibility: hidden;
181            top: 0;
182            left: 0;
183        }
184        </style>
185        <div class="container">
186            <div class="gasket"></div>
187        </div>
188
189        `;
190    }
191
192}
193