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