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';
17import { LitTable } from '../../../../base-ui/table/lit-table';
18import { MarkStruct } from '../../../bean/MarkStruct';
19import { SpSystemTrace } from '../../SpSystemTrace';
20import { getTimeString } from '../sheet/TabPaneCurrentSelection';
21import { Flag } from './Flag';
22
23@element('tabpane-flag')
24export class TabPaneFlag extends BaseElement {
25  private flag: Flag | null = null;
26  private flagList: Array<Flag> = [];
27  private systemTrace: SpSystemTrace | undefined | null;
28  private tableDataSource: Array<MarkStruct | unknown> = [];
29  private panelTable: LitTable | undefined | null;
30
31  initElements(): void {
32    this.systemTrace = document
33      .querySelector('body > sp-application')
34      ?.shadowRoot!.querySelector<SpSystemTrace>('#sp-system-trace');
35    this.panelTable = this.shadowRoot!.querySelector<LitTable>('.notes-editor-panel');
36    this.panelTable!.addEventListener('row-click', (evt: unknown) => {
37      // @ts-ignore
38      if (evt.detail.data.startTime === undefined) {
39        return;
40      }
41      this.flagList = this.systemTrace?.timerShaftEL!.sportRuler?.flagList || [];
42      // 点击表格某一行后,背景变色
43      // @ts-ignore
44      let data = evt.detail.data;
45      this.systemTrace!.flagList = this.flagList || [];
46      //   页面上对应的flag变为实心有旗杆
47      this.flagList.forEach((flag, index) => {
48        if (data.startTime === flag.time) {
49          flag.selected = true;
50          this.setTableSelection(index + 1);
51        } else {
52          flag.selected = false;
53        }
54        this.systemTrace?.timerShaftEL!.sportRuler!.drawTriangle(flag.time, flag.type);
55      });
56    });
57    // 当鼠标移出panel时重新加载备注信息
58    this.systemTrace?.shadowRoot?.querySelector('trace-sheet')?.addEventListener(
59      'mouseout',
60      (event: unknown) => {
61        if (this.flagList.length === 0) {
62          return;
63        }
64        let tr = this.panelTable!.shadowRoot!.querySelectorAll('.tr') as NodeListOf<HTMLDivElement>;
65        //   第一个tr是移除全部,所以跳过,从第二个tr开始,和this.slicestimeList数组的第一个对应……,所以i从1开始,在this.slicestimeList数组中取值时用i-1
66        for (let i = 1; i < tr.length; i++) {
67          tr[i].querySelector<HTMLInputElement>('#text-input')!.value = this.flagList[i - 1].text;
68        }
69        // @ts-ignore
70        event.stopPropagation();
71      },
72      { capture: true }
73    );
74    new ResizeObserver((entries) => {
75      if (this.parentElement!.style.display !== 'none') {
76        this.setTableData();
77      }
78    }).observe(this);
79  }
80
81  public setCurrentFlag(flag: Flag): void {
82    this.flagList = this.systemTrace?.timerShaftEL!.sportRuler?.flagList || [];
83    this.flag = flag;
84    // 判断当前传入的旗子是否已经存在
85    let findFlag = this.flagList.find((it) => it.time === flag.time);
86    // 如果this.flagList为空,或者没有在同一位置绘制过,就将当前的flag放进数组
87    if (!findFlag || this.flagList.length === 0) {
88      this.flagList!.push(this.flag);
89    }
90    this.setTableData();
91  }
92
93  /**
94   * 根据this.flagList设置表格数据
95   */
96  private setTableData(): void {
97    this.flagList = this.systemTrace?.timerShaftEL!.sportRuler?.flagList || [];
98    this.tableDataSource = [];
99    // 按照时间进行排序,保证泳道图上的旗子和表格的顺序一致
100    this.flagList.sort(function (a, b) {
101      return a.time - b.time;
102    });
103
104    for (let flag of this.flagList) {
105      let btn = document.createElement('button');
106      btn.className = 'remove';
107      let color = document.createElement('input');
108      color.type = 'color';
109      let text = document.createElement('input');
110      text.type = 'text';
111      color!.value = flag.color;
112      text!.value = flag.text;
113      let flagData = new MarkStruct(btn, color.value, text.value, getTimeString(flag.time), flag.time);
114      flag.selected === true ? (flagData.isSelected = true) : (flagData.isSelected = false);
115      this.systemTrace?.timerShaftEL!.sportRuler!.drawTriangle(flag.time, flag.type);
116      this.tableDataSource.push(flagData);
117    }
118    // 表格第一行只添加一个RemoveAll按钮
119    let removeAll = document.createElement('button');
120    removeAll.className = 'removeAll';
121    removeAll.innerHTML = 'RemoveAll';
122    let flagData = new MarkStruct(removeAll);
123    this.tableDataSource.unshift(flagData);
124
125    // 当前点击了哪个旗子,就将对应的表格中的那行的背景变色
126    this.tableDataSource.forEach((data, index) => {
127      // @ts-ignore
128      if (data.time === this.flag?.time) {
129        this.setTableSelection(index);
130      }
131    });
132    this.panelTable!.recycleDataSource = this.tableDataSource;
133    this.eventHandler();
134    this.systemTrace!.flagList = this.flagList || [];
135  }
136
137  /**
138   * 修改旗子颜色事件和移除旗子的事件处理
139   */
140  private eventHandler(): void {
141    let tr = this.panelTable!.shadowRoot!.querySelectorAll('.tr') as NodeListOf<HTMLDivElement>;
142    this.removeAllClickEventByFlag(tr[0]);
143    //   第一个tr是移除全部,所以跳过,从第二个tr开始,和this.flagList数组的第一个对应……,所以i从1开始,在this.flagList数组中取值时用i-1
144    for (let i = 1; i < tr.length; i++) {
145      tr[i].querySelector<HTMLInputElement>('#color-input')!.value = this.flagList[i - 1].color;
146      //  点击色块修改颜色
147      this.colorInputChangeEventByFlag(i, tr[i]);
148      // 修改备注
149      tr[i].querySelector<HTMLInputElement>('#text-input')!.value = this.flagList[i - 1].text;
150      this.textInputKeyUpEventByFlag(i, tr[i]);
151      this.textInputBlurEventByFlag(i, tr[i]);
152      this.textInputFocusEventByFlag(tr[i]);
153      // 点击remove按钮移除
154      this.removeClickEventByFlag(i, tr[i]);
155    }
156  }
157
158  private removeAllClickEventByFlag(tr: HTMLDivElement): void {
159    tr.querySelector('.removeAll')!.addEventListener('click', () => {
160      this.systemTrace!.flagList = [];
161      let flagList = [...this.flagList];
162      for (let i = 0; i < flagList.length; i++) {
163        flagList[i].hidden = true;
164        document.dispatchEvent(new CustomEvent('flag-change', { detail: flagList[i] }));
165      }
166      this.flagList = [];
167      return;
168    });
169  }
170
171  private colorInputChangeEventByFlag(index: number, tr: HTMLDivElement): void {
172    tr.querySelector<HTMLInputElement>('#color-input')?.addEventListener('change', (event: unknown) => {
173      // @ts-ignore
174      if (this.tableDataSource[index].startTime === this.flagList[index - 1].time) {
175        // @ts-ignore
176        this.flagList[index - 1].color = event?.target.value;
177        document.dispatchEvent(new CustomEvent('flag-change', { detail: this.flagList[index - 1] }));
178        //   旗子颜色改变时,重绘泳道图
179        this.systemTrace?.refreshCanvas(true);
180      }
181      // @ts-ignore
182      event.stopPropagation();
183    });
184  }
185
186  private textInputKeyUpEventByFlag(index: number, tr: HTMLDivElement): void {
187    tr.querySelector<HTMLInputElement>('#text-input')?.addEventListener('keyup', (event: unknown) => {
188      SpSystemTrace.isKeyUp = true;
189      // @ts-ignore
190      if (this.tableDataSource[index].startTime === this.flagList[index - 1].time && event.code === 'Enter' || event.code === 'NumpadEnter') {
191        // @ts-ignore
192        this.flagList[index - 1].text = event?.target.value;
193        document.dispatchEvent(new CustomEvent('flag-change', { detail: this.flagList[index - 1] }));
194        //   旗子颜色改变时,重绘泳道图
195        this.systemTrace?.refreshCanvas(true);
196      }
197      // @ts-ignore
198      event.stopPropagation();
199    });
200  }
201
202  private textInputBlurEventByFlag(index: number, tr: HTMLDivElement): void {
203    tr.querySelector<HTMLInputElement>('#text-input')?.addEventListener('blur', (event: unknown) => {
204      // @ts-ignore
205      (window as unknown).flagInputFocus = false;
206      window.publish(window.SmartEvent.UI.KeyboardEnable, {
207        enable: true,
208      });
209      // @ts-ignore
210      if (this.tableDataSource[index].startTime === this.flagList[index - 1].time) {
211        // @ts-ignore
212        this.flagList[index - 1].text = event?.target.value;
213        document.dispatchEvent(new CustomEvent('flag-change', { detail: this.flagList[index - 1] }));
214        this.setTableData();
215        //   旗子颜色改变时,重绘泳道图
216        this.systemTrace?.refreshCanvas(true);
217      }
218      // @ts-ignore
219      event.stopPropagation();
220    });
221  }
222
223  private textInputFocusEventByFlag(tr: HTMLDivElement): void {
224    tr.querySelector<HTMLInputElement>('#text-input')?.addEventListener('focus', (event: unknown) => {
225      // @ts-ignore
226      (window as unknown).flagInputFocus = true;
227      window.publish(window.SmartEvent.UI.KeyboardEnable, {
228        enable: false,
229      });
230      let tr = this.panelTable!.shadowRoot!.querySelectorAll('.tr') as NodeListOf<HTMLDivElement>;
231      //   第一个tr是移除全部,所以跳过,从第二个tr开始,和this.flagList数组的第一个对应……,所以i从1开始,在this.flagList数组中取值时用i-1
232      for (let i = 1; i < tr.length; i++) {
233        tr[i].querySelector<HTMLInputElement>('#text-input')!.value = this.flagList[i - 1].text;
234      }
235    });
236  }
237
238  private removeClickEventByFlag(index: number, tr: HTMLDivElement): void {
239    tr!.querySelector('.remove')?.addEventListener('click', (event: unknown) => {
240      // @ts-ignore
241      if (this.tableDataSource[index].startTime === this.flagList[index - 1].time) {
242        this.flagList[index - 1].hidden = true;
243        this.systemTrace!.flagList = this.flagList || [];
244        document.dispatchEvent(new CustomEvent('flag-change', { detail: this.flagList[index - 1] }));
245        //   移除时更新表格内容
246        this.setTableData();
247      }
248      // @ts-ignore
249      event.stopPropagation();
250    });
251  }
252
253  /**
254   * 修改表格指定行数的背景颜色
255   * @param line 要改变的表格行数
256   */
257  public setTableSelection(line: unknown): void {
258    // @ts-ignore
259    this.tableDataSource[line].isSelected = true;
260    // @ts-ignore
261    this.panelTable?.clearAllSelection(this.tableDataSource[line]);
262    // @ts-ignore
263    this.panelTable?.setCurrentSelection(this.tableDataSource[line]);
264  }
265
266  initHtml(): string {
267    return `
268        <style>
269        :host{
270            display: flex;
271            flex-direction: column;
272            padding: 10px 10px;
273        }
274        </style>
275        <lit-table class="notes-editor-panel" style="height: auto">
276            <lit-table-column width="20%" data-index="startTimeStr" key="startTimeStr" align="flex-start" title="TimeStamp">
277            </lit-table-column>
278            <lit-table-column width="10%" data-index="color" key="color" align="flex-start" title="Color">
279                <template>
280                    <div style='width:50px; height: 21px; position: relative;overflow: hidden;'>
281                        <input type="color" id="color-input" style='
282                            background: var(--dark-background5,#FFFFFF);
283                            padding: 0px;
284                            border: none;
285                            width: 60px;
286                            height: 31px;
287                            position: absolute;
288                            top: -5px;
289                            left: -5px;'/>
290                    </div>
291                </template>
292            </lit-table-column>
293            <lit-table-column width="40%" data-index="text" key="text" align="flex-start" title="Remarks">
294              <template>
295                  <input type="text" id="text-input"  style="width: 100%; border: none" /> 
296              </template>
297            </lit-table-column>
298            <lit-table-column width="10%" data-index="operate" key="operate" align="flex-start" title="Operate">
299                <template>
300                    <button class="remove" style='
301                        background: var(--dark-border1,#262f3c);
302                        color: white;
303                        border-radius: 10px;
304                        font-size: 10px;
305                        height: 21px;
306                        line-height: 21px;
307                        min-width: 7em;
308                        border: none;
309                        cursor: pointer;
310                        outline: inherit;
311                    '>Remove</button>
312                </template>
313            </lit-table-column>
314        </lit-table>
315        `;
316  }
317}
318