@antv/s2
Version:
effective spreadsheet render core lib
362 lines • 15.6 kB
JavaScript
import { find, first, forEach, get, includes, isEmpty, isEqual, map, merge, } from 'lodash';
import { BaseCell } from '../cell/base-cell';
import { CellType, EXTRA_COLUMN_FIELD, EXTRA_FIELD, S2Event, } from '../common/constant';
import { InteractionStateName } from '../common/constant/interaction';
import { GuiIcon } from '../common/icons';
import { includeCell } from '../utils/cell/data-cell';
import { getActionIconConfig, groupIconsByPosition, } from '../utils/cell/header-cell';
import { findFieldCondition } from '../utils/condition/condition';
import { renderIcon } from '../utils/g-renders';
import { getSortTypeIcon } from '../utils/sort-action';
export class HeaderCell extends BaseCell {
getHeaderConfig() {
return this.headerConfig || {};
}
isShallowRender() {
return super.isShallowRender() || this.headerConfig.shallowRender;
}
shouldInit() {
return super.shouldInit() && !this.isShallowRender();
}
handleRestOptions(...[headerConfig]) {
this.headerConfig = Object.assign({}, headerConfig);
const { value, query } = this.meta;
const sortParams = this.spreadsheet.dataCfg.sortParams || [];
// 该单元格是否为需要展示排序 icon 单元格
const isSortCell = this.isSortCell();
const sortParam = find([...sortParams].reverse(), (item) => isSortCell &&
(item === null || item === void 0 ? void 0 : item.sortByMeasure) === value &&
isEqual(get(item, 'query'), query));
const type = getSortTypeIcon(sortParam, isSortCell);
this.headerConfig.sortParam = Object.assign(Object.assign(Object.assign({}, this.headerConfig.sortParam), (sortParam || { query })), { type });
}
initCell() {
this.resetTextAndConditionIconShapes();
this.actionIcons = [];
this.hasDefaultHiddenIcon = false;
this.generateIconConfig();
}
generateIconConfig() {
var _a, _b;
this.conditionIconMappingResult = this.getIconConditionResult();
const { sortParam } = this.getHeaderConfig();
// 为什么有排序参数就不展示 actionIcon 了?背景不清楚,先照旧处理
if (this.showSortIcon()) {
this.actionIconConfig = {
icons: [
{
name: (sortParam === null || sortParam === void 0 ? void 0 : sortParam.type) || 'none',
position: 'right',
},
],
belongsCell: this
.cellType,
isSortIcon: true,
};
}
else {
this.actionIconConfig = getActionIconConfig(this.spreadsheet.options.headerActionIcons, this.meta, this.cellType);
}
this.groupedIcons = groupIconsByPosition((_b = (_a = this.actionIconConfig) === null || _a === void 0 ? void 0 : _a.icons) !== null && _b !== void 0 ? _b : [], this.conditionIconMappingResult);
}
getFormattedFieldValue() {
const { isTotalRoot, isGrandTotals, value } = this.meta;
const formatter = this.spreadsheet.dataSet.getFieldFormatter(this.meta.field);
/**
* 如果是 table mode,列头不需要被格式化
* 树状模式下,小计是父维度本身,需要被格式化,此时只有总计才不需要被格式化
* 平铺模式下,总计/小计 文字单元格,不需要被格式化
* 自定义树模式下,没有总计小计概念,isTotals 均为 false, 所以不受影响
*/
let shouldFormat = true;
if (this.spreadsheet.isTableMode()) {
shouldFormat = false;
}
else if (this.spreadsheet.isHierarchyTreeType()) {
shouldFormat = !(isGrandTotals && isTotalRoot);
}
else {
shouldFormat = !isTotalRoot;
}
const formattedValue = shouldFormat && formatter
? formatter(value, undefined, this.meta)
: value;
return {
formattedValue,
value,
};
}
showSortIcon() {
const { options, dataCfg } = this.spreadsheet;
const isEmptyValues = isEmpty(dataCfg.fields.values);
if (options.showDefaultHeaderActionIcon && !isEmptyValues) {
const { sortParam } = this.getHeaderConfig();
const query = this.meta.query;
if (this.isShallowRender()) {
return query;
}
// sortParam 的 query,和 type 本身可能会 undefined
return (query &&
isEqual(sortParam === null || sortParam === void 0 ? void 0 : sortParam.query, query) &&
(sortParam === null || sortParam === void 0 ? void 0 : sortParam.type) &&
(sortParam === null || sortParam === void 0 ? void 0 : sortParam.type) !== 'none');
}
return false;
}
getActionIconStyle(options) {
const { icon } = this.getStyle();
const conditionStyle = this.getTextConditionMappingResult();
const defaultTextFill = (conditionStyle === null || conditionStyle === void 0 ? void 0 : conditionStyle.fill) || this.getTextStyle().fill;
return {
width: icon === null || icon === void 0 ? void 0 : icon.size,
height: icon === null || icon === void 0 ? void 0 : icon.size,
// 优先级: 单个 icon 颜色配置 > 全部 icon 颜色配置 > 主题 icon 颜色配置 > 文本默认颜色
fill: options.fill === null
? undefined
: (options === null || options === void 0 ? void 0 : options.fill) || (icon === null || icon === void 0 ? void 0 : icon.fill) || defaultTextFill,
cursor: 'pointer',
};
}
// 是否设置为默认隐藏 action icon,默认隐藏的交互为 hover 后可见
hasDefaultHideActionIcon() {
return this.hasDefaultHiddenIcon;
}
addActionIcon(options) {
const { x, y, name, defaultHide, onClick, onHover, isSortIcon } = options;
const icon = new GuiIcon(Object.assign(Object.assign({}, this.getActionIconStyle(options)), { name,
x,
y }));
icon.toggleVisibility(!defaultHide);
icon.addEventListener('mouseover', (event) => {
this.spreadsheet.emit(S2Event.GLOBAL_ACTION_ICON_HOVER, event);
onHover === null || onHover === void 0 ? void 0 : onHover({
hovering: true,
name,
meta: this.meta,
event,
});
});
icon.addEventListener('mouseleave', (event) => {
this.spreadsheet.emit(S2Event.GLOBAL_ACTION_ICON_HOVER_OFF, event);
onHover === null || onHover === void 0 ? void 0 : onHover({
hovering: false,
name,
meta: this.meta,
event,
});
});
icon.addEventListener('click', (event) => {
this.spreadsheet.emit(S2Event.GLOBAL_ACTION_ICON_CLICK, event);
if (isSortIcon) {
this.spreadsheet.handleGroupSort(event, this.meta);
return;
}
onClick === null || onClick === void 0 ? void 0 : onClick({
name,
meta: this.meta,
event,
});
});
this.actionIcons.push(icon);
this.appendChild(icon);
}
drawActionAndConditionIcons() {
if (isEmpty(this.groupedIcons.left) && isEmpty(this.groupedIcons.right)) {
return;
}
if (!this.leftIconPosition || !this.rightIconPosition) {
return;
}
forEach(this.groupedIcons, (icons, position) => {
const { size, margin } = this.getStyle().icon;
const iconMargin = position === 'left' ? margin.right : margin.right;
const iconPosition = position === 'left' ? this.leftIconPosition : this.rightIconPosition;
forEach(icons, (icon, i) => {
var _a, _b, _c;
const x = iconPosition.x + (size + iconMargin) * i;
const y = iconPosition.y;
if (icon.isConditionIcon) {
this.conditionIconShape = renderIcon(this, {
x,
y,
name: icon.name,
width: size,
height: size,
fill: icon.fill,
});
this.addConditionIconShape(this.conditionIconShape);
return;
}
const { onClick, onHover, defaultHide, isSortIcon } = this.actionIconConfig;
const defaultHideHandler = (_a = icon.defaultHide) !== null && _a !== void 0 ? _a : defaultHide;
const iconDefaultHide = typeof defaultHideHandler === 'function'
? defaultHideHandler(this.meta, icon.name)
: defaultHideHandler;
if (iconDefaultHide) {
this.hasDefaultHiddenIcon = true;
}
this.addActionIcon({
name: icon.name,
fill: icon.fill,
x,
y,
defaultHide: iconDefaultHide,
onClick: (_b = icon.onClick) !== null && _b !== void 0 ? _b : onClick,
onHover: (_c = icon.onHover) !== null && _c !== void 0 ? _c : onHover,
isSortIcon,
});
});
});
}
isSortCell() {
var _a, _b, _c;
// 数值置于列头, 排序 icon 绘制在列头叶子节点; 置于行头, 排序 icon 绘制在行头叶子节点
const isValueInCols = (_b = (_a = this.spreadsheet) === null || _a === void 0 ? void 0 : _a.isValueInCols) === null || _b === void 0 ? void 0 : _b.call(_a);
const isMaxLevel = this.meta.level === ((_c = this.meta.hierarchy) === null || _c === void 0 ? void 0 : _c.maxLevel);
if (isValueInCols) {
return isMaxLevel && this.cellType === CellType.COL_CELL;
}
return isMaxLevel && this.cellType === CellType.ROW_CELL;
}
handleByStateName(cells, stateName) {
if (includeCell(cells, this)) {
this.updateByState(stateName);
}
}
handleSearchResult(cells) {
if (!includeCell(cells, this)) {
return;
}
const targetCell = find(cells, (cell) => cell === null || cell === void 0 ? void 0 : cell['isTarget']);
if (targetCell.id === this.getMeta().id) {
this.updateByState(InteractionStateName.HIGHLIGHT);
}
else {
this.updateByState(InteractionStateName.SEARCH_RESULT);
}
}
handleHover(cells) {
var _a;
if (includeCell(cells, this)) {
this.updateByState(InteractionStateName.HOVER);
if (this.hasDefaultHideActionIcon()) {
// hover 只会有一个 cell
this.toggleActionIcon((_a = cells === null || cells === void 0 ? void 0 : cells[0]) === null || _a === void 0 ? void 0 : _a.id);
}
}
}
handleSelect(cells, nodes = []) {
if (includeCell(cells, this)) {
this.updateByState(InteractionStateName.SELECTED);
}
const selectedNodeIds = map(nodes, 'id');
if (includes(selectedNodeIds, this.meta.id)) {
this.updateByState(InteractionStateName.SELECTED);
}
}
getTextStyle() {
const textOverflowStyle = this.getCellTextWordWrapStyle();
const { text, bolderText, measureText } = this.getStyle();
let style;
if (this.isMeasureField()) {
style = measureText || text;
}
else if (this.isBolderText()) {
style = bolderText;
}
else {
style = text;
}
return this.getContainConditionMappingResultTextStyle(Object.assign(Object.assign({}, textOverflowStyle), style));
}
getBackgroundColor() {
var _a;
const { backgroundColor, backgroundColorOpacity } = ((_a = this.getStyle()) === null || _a === void 0 ? void 0 : _a.cell) || {};
return merge({ backgroundColor, backgroundColorOpacity }, this.getBackgroundConditionFill());
}
toggleActionIcon(id) {
if (this.getMeta().id === id) {
const visibleActionIcons = [];
forEach(this.actionIcons, (icon) => {
// 仅存储当前不可见的 icon
if (icon.parsedStyle.visibility !== 'visible') {
icon.toggleVisibility(true);
visibleActionIcons.push(icon);
}
});
this.spreadsheet.store.set('visibleActionIcons', visibleActionIcons);
}
}
getIconPosition() {
return this.leftIconPosition || this.rightIconPosition;
}
getInteractedCells() {
var _a;
return (_a = this.spreadsheet.interaction) === null || _a === void 0 ? void 0 : _a.getCells([
CellType.CORNER_CELL,
CellType.COL_CELL,
CellType.ROW_CELL,
CellType.SERIES_NUMBER_CELL,
]);
}
update() {
const { interaction } = this.spreadsheet;
const stateInfo = interaction === null || interaction === void 0 ? void 0 : interaction.getState();
if ((stateInfo === null || stateInfo === void 0 ? void 0 : stateInfo.stateName) === InteractionStateName.ALL_SELECTED) {
this.updateByState(InteractionStateName.SELECTED);
return;
}
const cells = this.getInteractedCells();
if (!first(cells)) {
return;
}
switch (stateInfo === null || stateInfo === void 0 ? void 0 : stateInfo.stateName) {
case InteractionStateName.SELECTED:
case InteractionStateName.ROW_CELL_BRUSH_SELECTED:
case InteractionStateName.COL_CELL_BRUSH_SELECTED:
this.handleSelect(cells, stateInfo === null || stateInfo === void 0 ? void 0 : stateInfo.nodes);
break;
case InteractionStateName.HOVER_FOCUS:
case InteractionStateName.HOVER:
this.handleHover(cells);
break;
case InteractionStateName.SEARCH_RESULT:
this.handleSearchResult(cells);
break;
default:
this.handleByStateName(cells, stateInfo === null || stateInfo === void 0 ? void 0 : stateInfo.stateName);
break;
}
}
updateByState(stateName) {
super.updateByState(stateName, this);
}
hideInteractionShape() {
super.hideInteractionShape();
}
isMeasureField() {
return [EXTRA_FIELD, EXTRA_COLUMN_FIELD].includes(this.meta.field);
}
mappingValue(condition) {
var _a;
const value = this.getMeta().value;
return (_a = condition.mapping) === null || _a === void 0 ? void 0 : _a.call(condition, value, this.meta, this);
}
findFieldCondition(conditions = []) {
return findFieldCondition(conditions, this.meta.field);
}
getTreeIcon() {
return this.treeIcon;
}
getActionIcons() {
return this.actionIcons || [];
}
getMetaField() {
return this.meta.field;
}
destroy() {
this.meta.belongsCell = null;
super.destroy();
}
}
//# sourceMappingURL=header-cell.js.map