| // Copyright 2022 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import * as constant from '../src/constants'; |
| import { State } from '../src/state'; |
| import {html, LitElement} from 'lit'; |
| import {customElement} from 'lit/decorators.js'; |
| import { LogField } from '../src/fields'; |
| |
| @customElement('log-header') |
| export class LogHeader extends LitElement { |
| private maxWidths = {} as Record<string, number>; |
| private headerKeys: LogField[]; |
| |
| constructor(private state: State) { |
| super(); |
| const fields = this.state.currentFields; |
| const keys = Object.keys(fields).map(field => field as LogField); |
| this.headerKeys = keys; |
| for (let i = 0; i < keys.length; i++) { |
| const header = keys[i] as LogField; |
| this.maxWidths[header] = 0; |
| } |
| } |
| |
| render() { |
| const fields = this.state.currentFields; |
| return html` |
| |
| ${this.headerKeys.map((field, i) => { |
| return html` |
| <div |
| id="${field}" |
| aria-label="${fields[field].displayName}" |
| aria-colindex="${i + 1}" |
| style="width: ${fields[field].width}"> |
| ${fields[field].displayName} |
| ${(i !== this.headerKeys.length - 1) ? (html` |
| <div |
| class="column-resize" |
| ></div> |
| `) : ''} |
| </div> |
| `; |
| })} |
| `; |
| } |
| |
| protected createRenderRoot() { |
| return this; |
| } |
| |
| public setMaxCellWidth(id: LogField, maxWidth: number): void { |
| this.maxWidths[id] = maxWidth; |
| }; |
| |
| firstUpdated(changedProperties: any) { |
| super.firstUpdated(changedProperties); |
| const resizers = this.querySelectorAll('.column-resize'); |
| for (const index in Array.from(resizers)) { |
| const curResizer = resizers[index]; |
| createResizableColumn( |
| this.state, |
| this.maxWidths, |
| curResizer.parentElement!, |
| curResizer as HTMLElement); |
| } |
| } |
| } |
| |
| /** |
| * Creates resizable element in header to determine column size. |
| * @param header identify which header is active. |
| * @param cell header cell of the column. |
| * @param resizer element in the header cell that handles the resizing. |
| */ |
| function createResizableColumn(state: State, maxWidths: Record<string, number>, |
| cell: HTMLElement, resizer: HTMLElement) { |
| |
| let header = cell.id as LogField; |
| let w = 0; |
| let x = 0; |
| |
| const mouseDoubleClickHandler = function () { |
| cell.style.width = `${maxWidths[header]}px`; |
| state.setHeaderWidth(header, cell.style.width); |
| }; |
| |
| const mouseDownHandler = function (e: MouseEvent) { |
| x = e.clientX; |
| w = cell.clientWidth; |
| |
| document.addEventListener('mousemove', mouseMoveHandler); |
| document.addEventListener('mouseup', mouseUpHandler); |
| |
| resizer.classList.add('resizing'); |
| }; |
| |
| const mouseMoveHandler = function (e: MouseEvent) { |
| const dx = e.clientX - x; |
| if ((w + dx) > constant.COL_MINWIDTH) { |
| cell.style.width = `${w + dx}px`; |
| state.setHeaderWidth(header, cell.style.width); |
| } |
| }; |
| |
| const mouseUpHandler = function () { |
| resizer.classList.remove('resizing'); |
| document.removeEventListener('mousemove', mouseMoveHandler); |
| document.removeEventListener('mouseup', mouseUpHandler); |
| }; |
| |
| resizer.addEventListener('mousedown', mouseDownHandler); |
| resizer.addEventListener('dblclick', mouseDoubleClickHandler); |
| } |
| |