Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(cell): unify cell functions #136

Merged
merged 16 commits into from
Aug 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/s2-core/scripts/test-live.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ async function main() {
type: 'rawlist',
message: '📢 请选择测试文件 (输入序号可快速选择)',
name: 'path',
loop: false,
choices: paths,
default: () => defaultSelectedIndex,
},
Expand Down
62 changes: 34 additions & 28 deletions packages/s2-core/src/cell/base-cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ import {
SHAPE_ATTRS_MAP,
SHAPE_STYLE_MAP,
} from '@/common/constant';
import { InteractionStateTheme, SpreadSheetTheme } from '@/common/interface';
import { SpreadSheetTheme } from '@/common/interface';
import { Group, IShape } from '@antv/g-canvas';
import { each, findKey, get, includes } from 'lodash';
import { SpreadSheet } from '../sheet-type';
import { updateShapeAttr } from '../utils/g-renders';
import { StateShapeLayer } from './../common/interface/interaction';

export abstract class BaseCell<T> extends Group {
// used to determine the cell type
public cellType: CellTypes;

// cell's data meta info
protected meta: T;

Expand All @@ -23,19 +21,14 @@ export abstract class BaseCell<T> extends Group {
// spreadsheet's theme
protected theme: SpreadSheetTheme;

// background control by icon condition
// background control shape
protected backgroundShape: IShape;

// text control shape
protected textShape: IShape;

// render interactive background,
protected interactiveBgShape: IShape;

// 需要根据state改变样式的shape集合
// 需要这个属性的原因是在state clear时知道具体哪些shape要hide。不然只能手动改,比较麻烦
protected stateShapes: IShape[] = [];

// protected actionIcons: GuiIcon[];
// interactive control shapes, unify read and manipulate operations
protected stateShapes = new Map<StateShapeLayer, IShape>();

public constructor(
meta: T,
Expand All @@ -50,11 +43,6 @@ export abstract class BaseCell<T> extends Group {
this.initCell();
}

/**
* Update cell's selected state
*/
public abstract update(): void;

public getMeta(): T {
return this.meta;
}
Expand All @@ -67,31 +55,49 @@ export abstract class BaseCell<T> extends Group {
* in case there are more params to be handled
* @param options any type's rest params
*/
protected handleRestOptions(...options: any) {
protected handleRestOptions(...options: unknown[]) {
// default do nothing
}

/**
* Return the type of the cell
*/
public abstract get cellType(): CellTypes;

/**
* Determine how to render this cell area
*/
protected abstract initCell(): void;

/**
* Return the type of the cell
* Update cell's selected state
*/
protected abstract getCellType(): CellTypes;
public abstract update(): void;

/* -------------------------------------------------------------------------- */
/* common functions that will be used in subtype */
/* -------------------------------------------------------------------------- */

// 根据当前state来更新cell的样式
public updateByState(stateName: InteractionStateName) {
const stateStyles = get(this.theme, `${this.cellType}.cell.${stateName}`);
const stateStyles = get(
this.theme,
`${this.cellType}.cell.interactionState.${stateName}`,
);
each(stateStyles, (style, styleKey) => {
if (styleKey) {
const currentShape = findKey(SHAPE_ATTRS_MAP, (attrs) =>
includes(attrs, styleKey),
);
if (!currentShape) return;
updateShapeAttr(this[currentShape], SHAPE_STYLE_MAP[styleKey], style);
const currentShape = findKey(SHAPE_ATTRS_MAP, (attrs) =>
includes(attrs, styleKey),
) as StateShapeLayer | undefined;

if (!currentShape || !this.stateShapes.has(currentShape)) {
return;
}

updateShapeAttr(
this.stateShapes.get(currentShape),
SHAPE_STYLE_MAP[styleKey],
style,
);
});
}

Expand Down
110 changes: 45 additions & 65 deletions packages/s2-core/src/cell/col-cell.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,32 @@
import { BaseCell } from '@/cell/base-cell';
import {
CellTypes,
COLOR_DEFAULT_RESIZER,
KEY_GROUP_COL_RESIZER,
InteractionStateName,
} from '@/common/constant';
import { GuiIcon } from '@/common/icons';
import { TextAlign } from '@/common/interface';
import { HIT_AREA } from '@/facet/header/base';
import { ColHeaderConfig } from '@/facet/header/col';
import { ResizeInfo } from '@/facet/header/interface';
import { Node } from '@/index';
import { renderRect } from '@/utils/g-renders';
import { renderLine, renderRect, renderText } from '@/utils/g-renders';
import {
getEllipsisText,
getTextPosition,
measureTextWidth,
} from '@/utils/text';
import { IGroup } from '@antv/g-canvas';
import _ from 'lodash';
import { get, isEqual } from 'lodash';
import { HeaderCell } from './header-cell';

export class ColCell extends BaseCell<Node> {
export class ColCell extends HeaderCell {
protected headerConfig: ColHeaderConfig;

public update() {
const stateName = this.spreadsheet.interaction.getCurrentStateName();
const cells = this.spreadsheet.interaction.getActiveCells();
const currentCell = _.first(cells);
if (
!currentCell ||
(stateName !== InteractionStateName.HOVER &&
stateName !== InteractionStateName.HOVER_FOCUS)
) {
return;
}
if (currentCell?.cellType === CellTypes.DATA_CELL || cells.includes(this)) {
this.updateByState(InteractionStateName.HOVER);
}
}

protected handleRestOptions(...options: ColHeaderConfig[]) {
this.headerConfig = options[0];
public get cellType() {
return CellTypes.COL_CELL;
}

protected initCell() {
this.cellType = this.getCellType();
// draw rect background
// 1、draw rect background
this.drawRectBackground();
// interactive background shape
this.drawInteractiveBgShape();
Expand All @@ -57,14 +38,9 @@ export class ColCell extends BaseCell<Node> {
this.drawRightBorder();
// draw hot-spot rect
this.drawHotSpot();
// update the interaction state
this.update();
wjgogogo marked this conversation as resolved.
Show resolved Hide resolved
}

protected getCellType() {
return CellTypes.COL_CELL;
}

protected getColHotSpotKey() {
return this.meta.key;
}
Expand All @@ -82,12 +58,8 @@ export class ColCell extends BaseCell<Node> {
}

protected drawCellText() {
const {
offset,
width,
scrollContainsRowHeader,
cornerWidth,
} = this.headerConfig;
const { offset, width, scrollContainsRowHeader, cornerWidth } =
this.headerConfig;
const {
label,
x,
Expand All @@ -114,7 +86,7 @@ export class ColCell extends BaseCell<Node> {
? iconCfg.size + iconCfg.margin.right
: 0;
const textStyle = isLeaf && !isTotals ? textCfg : bolderTextCfg;
const padding = _.get(this, 'theme.colCell.cell.padding');
const padding = get(this, 'theme.colCell.cell.padding');
wjgogogo marked this conversation as resolved.
Show resolved Hide resolved
const text = getEllipsisText(
content,
cellWidth - sortIconPadding - padding?.left - padding?.right,
Expand All @@ -126,8 +98,8 @@ export class ColCell extends BaseCell<Node> {
let textAlign: TextAlign;
if (isLeaf) {
// 最后一个层级的维值,与 dataCell 对齐方式保持一致
textAlign = _.get(this, 'theme.dataCell.text.textAlign');
const textBaseline = _.get(this, 'theme.dataCell.text.textBaseline');
textAlign = this.theme.dataCell.text.textAlign;
const textBaseline = this.theme.dataCell.text.textBaseline;
textStyle.textBaseline = textBaseline;
const cellBoxCfg = {
x,
Expand Down Expand Up @@ -183,7 +155,7 @@ export class ColCell extends BaseCell<Node> {
}
// const derivedValue = this.spreadsheet.getDerivedValue(value);
// if (
// !_.isEqual(
// !isEqual(
// derivedValue.derivedValueField,
// derivedValue.displayDerivedValueField,
// ) &&
Expand All @@ -197,44 +169,48 @@ export class ColCell extends BaseCell<Node> {
// if (
// key === EXTRA_FIELD &&
// this.spreadsheet.isDerivedValue(value) &&
// _.last(derivedValue.displayDerivedValueField) === value
// last(derivedValue.displayDerivedValueField) === value
// ) {
// // 度量列,找到 value值
// text += '...';
// }
// }
this.addShape('text', {
attrs: {
x: textX,
y: textY,
text,
this.textShape = renderText(
this,
[this.textShape],
textX,
textY,
text,
{
textAlign,
...textStyle,
cursor: 'pointer',
},
});
{ cursor: 'pointer' },
);
}

// 交互使用的背景色
protected drawInteractiveBgShape() {
const { x, y, height, width } = this.meta;
this.interactiveBgShape = renderRect(this, {
x,
y,
width,
height,
fill: 'transparent',
stroke: 'transparent',
});
this.stateShapes.push(this.interactiveBgShape);
this.stateShapes.set(
'interactiveBgShape',
renderRect(this, {
x,
y,
width,
height,
fill: 'transparent',
stroke: 'transparent',
}),
);
}

private showSortIcon() {
const { sortParam } = this.headerConfig;
const query = this.meta.query;
return (
_.isEqual(_.get(sortParam, 'query'), query) &&
_.get(sortParam, 'type') !== 'none'
isEqual(get(sortParam, 'query'), query) &&
get(sortParam, 'type') !== 'none'
);
}

Expand All @@ -245,7 +221,7 @@ export class ColCell extends BaseCell<Node> {
const { sortParam } = this.headerConfig;
const { x, y, width: cellWidth, height: cellHeight } = this.meta;
const iconShape = new GuiIcon({
type: _.get(sortParam, 'type', 'none'),
type: get(sortParam, 'type', 'none'),
x: x + cellWidth - icon.size - icon.margin.right,
y: y + (cellHeight - icon.size) / 2,
width: icon.size,
Expand Down Expand Up @@ -334,16 +310,20 @@ export class ColCell extends BaseCell<Node> {
if (!this.meta.isLeaf) {
const { height, viewportHeight } = this.headerConfig;
const { x, y, width: cellWidth, height: cellHeight } = this.meta;
this.addShape('line', {
attrs: {

renderLine(
this,
{
x1: x + cellWidth,
y1: y + cellHeight,
x2: x + cellWidth,
y2: y + height + viewportHeight, // 高度有多,通过 clip 裁剪掉
y2: y + height + viewportHeight,
},
{
stroke: this.theme.colCell.cell.horizontalBorderColor,
lineWidth: 1,
},
});
);
}
}
}
Loading