• 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';
16import { TraceRowObject } from './TraceRowObject';
17import { TraceRow } from './TraceRow';
18import { log } from '../../../../log/Log';
19// @ts-ignore
20@element('trace-row-recycler-view')
21export class TraceRowRecyclerView extends BaseElement {
22  private recycler: boolean = true;
23  private gasketEL: HTMLDivElement | null | undefined;
24  private vessel: HTMLDivElement | null | undefined;
25  private visibleRowsCount: number = 0; // @ts-ignore
26  private visibleObjects: TraceRowObject<unknown>[] = [];
27  private totalHeight: number = 0;
28  // @ts-ignore
29  private _dataSource: Array<TraceRowObject<unknown>> = [];
30  private _renderType: string = 'div';
31  // @ts-ignore
32  get dataSource(): Array<TraceRowObject<unknown>> {
33    return this._dataSource;
34  }
35  // @ts-ignore
36  set dataSource(value: Array<TraceRowObject<unknown>>) {
37    log(`dataSource TraceRowObject size :${value.length}`);
38    this._dataSource = value;
39    this.measureHeight();
40    this.initUI(); // @ts-ignore
41    let els = [...this.shadowRoot!.querySelectorAll<TraceRow<unknown>>('.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  // @ts-ignore
55  refreshRow(el: TraceRow<unknown>, obj: TraceRowObject<unknown>): void {
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  initElements(): void {
79    this.vessel = this.shadowRoot?.querySelector<HTMLDivElement>('.vessel');
80    this.gasketEL = this.shadowRoot?.querySelector<HTMLDivElement>('.gasket'); // @ts-ignore
81    let els: Array<TraceRow<unknown>> | undefined | null;
82    this.vessel!.onscroll = (ev): void => {
83      let top = this.vessel!.scrollTop;
84      let skip = 0;
85      for (let index = 0; index < this.visibleObjects.length; index++) {
86        if (this.visibleObjects[index].top >= top) {
87          skip = this.visibleObjects[index].rowIndex - 1;
88          break;
89        }
90      }
91      if (skip < 0) {
92        skip = 0;
93      }
94      if (!els) {
95        // @ts-ignore
96        els = [...this.shadowRoot!.querySelectorAll<TraceRow<unknown>>('.recycler-cell')];
97      }
98      for (let i = 0; i < els.length; i++) {
99        let obj = this.visibleObjects[i + skip];
100        this.refreshRow(els[i], obj);
101      }
102    };
103  }
104
105  measureHeight(): void {
106    this.visibleObjects = this.dataSource.filter((it) => !it.rowHidden);
107    this.totalHeight = this.visibleObjects.map((it) => it.rowHeight).reduce((a, b) => a + b);
108    let totalHeight = 0;
109    for (let i = 0; i < this.visibleObjects.length; i++) {
110      this.visibleObjects[i].top = totalHeight;
111      this.visibleObjects[i].rowIndex = i;
112      totalHeight += this.visibleObjects[i].rowHeight;
113      this.visibleObjects[i].preObject = i === 0 ? null : this.visibleObjects[i - 1];
114      this.visibleObjects[i].nextObject = i === this.visibleObjects.length - 1 ? null : this.visibleObjects[i + 1];
115    }
116    this.gasketEL && (this.gasketEL.style.height = `${this.totalHeight}px`);
117  }
118
119  initUI(): void {
120    this.visibleRowsCount = Math.ceil(this.clientHeight / 40);
121    if (this.visibleRowsCount >= this.visibleObjects.length) {
122      this.visibleRowsCount = this.visibleObjects.length;
123    }
124    if (!this.recycler) {
125      this.visibleRowsCount = this.dataSource.length;
126    }
127    for (let i = 0; i <= this.visibleRowsCount; i++) {
128      // @ts-ignore
129      let el = new TraceRow<unknown>({
130        canvasNumber: 1,
131        alpha: true,
132        contextId: '2d',
133        isOffScreen: true,
134      });
135      el.className = 'recycler-cell';
136      this.vessel?.appendChild(el);
137      el.addEventListener('expansion-change', (ev: unknown): void => {
138        // @ts-ignore
139        el.obj!.expansion = ev.detail.expansion;
140        for (let j = 0; j < this.dataSource.length; j++) {
141          // @ts-ignore
142          if (this.dataSource[j].rowParentId === ev.detail.rowId) {
143            // @ts-ignore
144            this.dataSource[j].rowHidden = !ev.detail.expansion;
145          }
146        }
147        this.measureHeight(); // @ts-ignore
148        let els = [...this.shadowRoot!.querySelectorAll<TraceRow<unknown>>('.recycler-cell')];
149        let top = this.vessel!.scrollTop;
150        let skip = 0;
151        for (let i = 0; i < this.visibleObjects.length; i++) {
152          if (this.visibleObjects[i].top >= top) {
153            skip = this.visibleObjects[i].rowIndex - 1;
154            break;
155          }
156        }
157        if (skip < 0) {
158          skip = 0;
159        }
160        for (let i = 0; i < els.length; i++) {
161          let obj = this.visibleObjects[i + skip];
162          this.refreshRow(els[i], obj);
163        }
164      });
165    }
166  }
167
168  initHtml(): string {
169    return `
170        <style>
171        :host{
172            width:100%;
173            height:100%;
174            display: block;
175            position:relative;
176        }
177        .vessel{
178            width:100%;
179            height:100%;
180            overflow: auto;
181            position: absolute;
182            display: block;
183        }
184        .gasket{
185            width:100%;
186            height:auto;
187            top: 0;
188            left: 0;
189            right:0;
190            bottom:0;
191            visibility: hidden;
192        }
193        .recycler-cell{
194            position: absolute;
195            width:100%;
196            visibility: hidden;
197            top: 0;
198            left: 0;
199        }
200        </style>
201        <div class="vessel">
202            <div class="gasket"></div>
203        </div>
204
205        `;
206  }
207}
208