UNPKG

e-virt-table

Version:

A powerful data table based on canvas. You can use it as data grid、Microsoft Excel or Google sheets. It supports virtual scroll、cell edit etc.

640 lines 22.5 kB
import { generateShortUUID } from './util'; import BaseCell from './BaseCell'; export default class CellHeader extends BaseCell { constructor(ctx, colIndex, x, y, width, height, column) { super(ctx, x, y, width, height, 'header', column.fixed); Object.defineProperty(this, "align", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "hideHeaderSelection", { enumerable: true, configurable: true, writable: true, value: false }); Object.defineProperty(this, "verticalAlign", { enumerable: true, configurable: true, writable: true, value: 'middle' }); Object.defineProperty(this, "fixed", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "minWidth", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "maxWidth", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "widthFillDisable", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "type", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "operation", { enumerable: true, configurable: true, writable: true, value: false }); Object.defineProperty(this, "editorType", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "level", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "text", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "hide", { enumerable: true, configurable: true, writable: true, value: false }); Object.defineProperty(this, "displayText", { enumerable: true, configurable: true, writable: true, value: '' }); Object.defineProperty(this, "colspan", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "rowspan", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "row", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "key", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "required", { enumerable: true, configurable: true, writable: true, value: false }); Object.defineProperty(this, "readonly", { enumerable: true, configurable: true, writable: true, value: false }); Object.defineProperty(this, "ellipsis", { enumerable: true, configurable: true, writable: true, value: false }); Object.defineProperty(this, "overflowTooltipShow", { enumerable: true, configurable: true, writable: true, value: true }); Object.defineProperty(this, "children", { enumerable: true, configurable: true, writable: true, value: [] }); Object.defineProperty(this, "column", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "colIndex", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "rowKey", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "rules", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "hasChildren", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "render", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "style", { enumerable: true, configurable: true, writable: true, value: {} }); Object.defineProperty(this, "drawX", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "drawY", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "sortIconName", { enumerable: true, configurable: true, writable: true, value: 'sort-default' }); Object.defineProperty(this, "sortAscIconName", { enumerable: true, configurable: true, writable: true, value: 'sort-asc' }); Object.defineProperty(this, "sortDescIconName", { enumerable: true, configurable: true, writable: true, value: 'sort-desc' }); Object.defineProperty(this, "visibleWidth", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "visibleHeight", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "maxLineClampHeader", { enumerable: true, configurable: true, writable: true, value: 'auto' }); Object.defineProperty(this, "domDataset", { enumerable: true, configurable: true, writable: true, value: {} }); Object.defineProperty(this, "drawTextX", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "drawTextY", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "drawTextWidth", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "drawTextHeight", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "drawCellBgColor", { enumerable: true, configurable: true, writable: true, value: '' }); Object.defineProperty(this, "drawTextColor", { enumerable: true, configurable: true, writable: true, value: '' }); Object.defineProperty(this, "drawTextFont", { enumerable: true, configurable: true, writable: true, value: '' }); Object.defineProperty(this, "drawSelectionImageX", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "drawSelectionImageY", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "drawSelectionImageWidth", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "drawSelectionImageHeight", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "drawSelectionImageName", { enumerable: true, configurable: true, writable: true, value: '' }); Object.defineProperty(this, "drawSelectionImageSource", { enumerable: true, configurable: true, writable: true, value: void 0 }); // 排序相关 Object.defineProperty(this, "drawSortImageX", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "drawSortImageY", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "drawSortImageWidth", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "drawSortImageHeight", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "drawSortImageName", { enumerable: true, configurable: true, writable: true, value: '' }); Object.defineProperty(this, "drawSortImageSource", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.ctx = ctx; this.x = x; this.y = y; this.width = width; this.height = height; this.visibleWidth = width; this.visibleHeight = height; this.colIndex = colIndex; this.key = column.key; this.minWidth = column.minWidth; this.maxWidth = column.maxWidth; this.hide = (typeof column.hide === 'function' ? column.hide(column) : column.hide) || false; this.type = column.type || ''; this.editorType = column.editorType || 'text'; this.hideHeaderSelection = column.hideHeaderSelection || false; this.align = column.headerAlign || column.align || this.ctx.config.COLUMNS_ALIGN; this.verticalAlign = column.headerVerticalAlign || column.verticalAlign || this.ctx.config.COLUMNS_VERTICAL_ALIGN; this.fixed = column.fixed || ''; this.level = column.level || 0; this.operation = column.operation || false; this.text = column.title; this.column = column; this.colspan = column.colspan || 1; this.widthFillDisable = column.widthFillDisable || false; this.rowspan = column.rowspan || 1; this.rules = column.rules; this.readonly = column.readonly || false; this.required = column.required || false; this.sortIconName = column.sortIconName || 'sort-default'; this.sortAscIconName = column.sortAscIconName || 'sort-asc'; this.sortDescIconName = column.sortDescIconName || 'sort-desc'; this.rowKey = generateShortUUID(); this.overflowTooltipShow = column.overflowTooltipHeaderShow === false ? false : true; this.hasChildren = (column.children && column.children.length > 0) || false; // 是否有子 this.render = column.renderHeader; this.maxLineClampHeader = column.maxLineClampHeader || 'auto'; } /** * 是否可见,覆盖基类方法,表头是跟y滚动条没有关系的所以不需要加滚动参数 * @returns */ isVerticalVisible() { const { stageHeight } = this.ctx; const offsetHeight = stageHeight; return !(this.y + this.height <= 0 || this.y >= offsetHeight); } /** * 更新样式 */ updateStyle() { this.style = this.getOverlayerViewsStyle(); } updateContainer() { const { HEADER_CELL_STYLE_METHOD, HEADER_BG_COLOR, HEADER_TEXT_COLOR } = this.ctx.config; let bgColor = HEADER_BG_COLOR; let textColor = HEADER_TEXT_COLOR; if (typeof HEADER_CELL_STYLE_METHOD === 'function') { const headerCellStyleMethod = HEADER_CELL_STYLE_METHOD; const { backgroundColor, color, font } = headerCellStyleMethod({ colIndex: this.colIndex, column: this.column, }) || {}; if (backgroundColor) { bgColor = backgroundColor; } // 文字颜色 if (color) { textColor = color; } if (font) { this.drawTextFont = font; } } // 高亮查找结果 const { colKey, type } = this.ctx.finderBar; if (type === 'header' && colKey === this.key) { bgColor = this.ctx.config.FINDER_CELL_BG_COLOR; } this.drawCellBgColor = bgColor; this.drawTextColor = textColor; } update() { this.updateContainer(); this.displayText = this.getText(); this.drawX = this.getDrawX(); this.drawY = this.getDrawY(); this.drawTextX = this.drawX; this.drawTextY = this.drawY; this.drawTextWidth = this.width; this.drawTextHeight = this.height; this.updateStyle(); } draw() { this.drawEdge(); this.drawSelection(); this.drawText(); this.drawBg(); this.drawSortIcon(); } drawEdge() { const { paint, config: { BORDER_COLOR, BORDER }, } = this.ctx; // 有边框的情况下,绘制边框 paint.drawRect(this.drawX, this.drawY, this.width, this.height, { borderColor: BORDER ? BORDER_COLOR : 'transparent', fillColor: this.drawCellBgColor, }); } drawText() { const { paint, config: { HEADER_FONT, CELL_PADDING, REQUIRED_COLOR }, } = this.ctx; const cacheTextKey = `${this.displayText}_${this.drawTextWidth}_${this.drawTextFont}`; this.ellipsis = paint.drawText(this.displayText, this.drawTextX, this.drawTextY, this.drawTextWidth, this.drawTextHeight, { font: this.drawTextFont || HEADER_FONT, padding: CELL_PADDING, color: this.drawTextColor, align: this.align, verticalAlign: this.verticalAlign, maxLineClamp: this.maxLineClampHeader, offsetRight: this.column.sortBy ? 16 : 0, // 排序图标占位 offsetLeft: this.required ? 12 : 0, // 必填星号占位 cacheTextKey, textCallback: (textInfo) => { // 排序图标位置,需要跟随文字变化 if (this.column.sortBy) { this.drawSortImageX = textInfo.right + 4; this.drawSortImageY = textInfo.top + (textInfo.height - 16) / 2; } if (this.required) { paint.drawText('*', textInfo.left - 18, textInfo.top + (textInfo.height - 12) / 2, 24, 24, { color: REQUIRED_COLOR, font: '18px Arial', align: 'center', verticalAlign: 'middle', padding: 0, }); } }, }); } drawBg() { if (this.ctx.dragHeaderIng) { return; } // 选择区背景颜色 const { ENABLE_SELECTOR, ENABLE_SELECTOR_SINGLE } = this.ctx.config; let minX = -1; let maxX = -1; if (this.ctx.focusCellHeader) { minX = this.ctx.focusCellHeader.colIndex; maxX = this.ctx.focusCellHeader.colIndex + this.ctx.focusCellHeader.colspan - 1; } // 启用选择器且不是单选 if (ENABLE_SELECTOR && !ENABLE_SELECTOR_SINGLE) { const { xArr } = this.ctx.selector; minX = xArr[0]; maxX = xArr[1]; } const colSpanMaxIndex = this.colspan + this.colIndex - 1; if (this.colIndex >= minX && this.colIndex <= maxX && colSpanMaxIndex <= maxX) { this.ctx.paint.drawRect(this.drawX, this.drawY, this.width, this.height, { borderColor: 'transparent', fillColor: this.ctx.config.SELECT_ROW_COL_BG_COLOR || 'transparent', }); } } drawSelection() { if (this.hideHeaderSelection) { return; } // 选中框类型 if (['index-selection', 'selection', 'selection-tree', 'tree-selection'].includes(this.type)) { const { indeterminate, check, selectable } = this.ctx.database.getCheckedState(); const { CHECKBOX_SIZE = 0, CELL_PADDING } = this.ctx.config; // 默认居中 let iconX = this.drawX + (this.width - CHECKBOX_SIZE) / 2; let iconY = this.drawY + (this.height - CHECKBOX_SIZE) / 2; this.drawTextX = iconX + CHECKBOX_SIZE - CELL_PADDING / 2; this.drawTextWidth = this.drawX + this.visibleWidth - this.drawTextX; if (this.align === 'left' || this.align === 'right') { iconX = this.drawX + CELL_PADDING; this.drawTextX = iconX + CHECKBOX_SIZE - CELL_PADDING / 2; this.drawTextWidth = this.drawX + this.visibleWidth - this.drawTextX; } if (this.verticalAlign === 'top') { iconY = this.drawY + CELL_PADDING / 2; } else if (this.verticalAlign === 'bottom') { iconY = this.drawY + this.height - CHECKBOX_SIZE - CELL_PADDING / 2; } let checkboxImage = this.ctx.icons.get('checkbox-uncheck'); let checkboxName = 'checkbox-uncheck'; if (indeterminate) { checkboxImage = this.ctx.icons.get('checkbox-indeterminate'); checkboxName = 'checkbox-indeterminate'; } else if (check && selectable) { checkboxImage = this.ctx.icons.get('checkbox-check'); checkboxName = 'checkbox-check'; } else if (check && !selectable) { checkboxImage = this.ctx.icons.get('checkbox-check-disabled'); checkboxName = 'checkbox-check-disabled'; } else if (!check && selectable) { checkboxImage = this.ctx.icons.get('checkbox-uncheck'); checkboxName = 'checkbox-uncheck'; } else { checkboxImage = this.ctx.icons.get('checkbox-disabled'); checkboxName = 'checkbox-disabled'; } if (checkboxImage) { this.drawSelectionImageX = iconX; this.drawSelectionImageY = iconY; this.drawSelectionImageWidth = CHECKBOX_SIZE; this.drawSelectionImageHeight = CHECKBOX_SIZE; this.drawSelectionImageName = checkboxName; this.drawSelectionImageSource = checkboxImage; this.ctx.paint.drawImage(this.drawSelectionImageSource, this.drawSelectionImageX, this.drawSelectionImageY, this.drawSelectionImageWidth, this.drawSelectionImageHeight); } // 不再需要保存文本位置信息,直接在 draw 方法中计算 } } drawSortIcon() { // 如果没有sortBy配置且不是后端排序,不显示排序图标 if (!this.column.sortBy) { return; } const iconSize = 16; let iconName = this.sortIconName; // 前端排序 const sortState = this.ctx.database.getSortState(this.key); if (sortState.direction === 'asc') { iconName = this.sortAscIconName; } else if (sortState.direction === 'desc') { iconName = this.sortDescIconName; } const icon = this.ctx.icons.get(iconName); if (!icon) { return; } this.drawSortImageWidth = iconSize; this.drawSortImageHeight = iconSize; this.drawSortImageName = iconName; this.drawSortImageSource = icon; // 绘制图标 this.ctx.paint.drawImage(this.drawSortImageSource, this.drawSortImageX, this.drawSortImageY, this.drawSortImageWidth, this.drawSortImageHeight); } getText() { if (this.render) { return ''; } if (['', null, undefined].includes(this.text)) { return ''; } return `${this.text}`; } /** * 获取样式 */ getOverlayerViewsStyle() { let left = ''; if (this.fixed === 'left') { left = `${this.drawX}px`; } else if (this.fixed === 'right') { left = `${this.drawX - (this.ctx.stageWidth - this.ctx.fixedRightWidth)}px`; } else { // 中间的,需要减去左边固定列的宽度 left = `${this.drawX - this.ctx.fixedLeftWidth}px`; } return { position: 'absolute', overflow: 'hidden', left: left, top: `${this.drawY + 1}px`, width: `${this.width}px`, height: `${this.height - 2}px`, pointerEvents: 'initial', userSelect: 'none', }; } } //# sourceMappingURL=CellHeader.js.map