import * as React from 'react'; import { IStoreState, ID, EditorUsage, ISelectionType, IRow, ICell, IColumn, IRowDimensions, IColDimensions, } from '../index.data'; import DataSheet from '../DataSheet'; import { connect } from 'unistore/react'; import styles from './index.less'; import Selected from '../Selected'; import { fsmPred } from '../StateMachine/helper'; import HighlightedCells from '../HighlightedCells'; import RuntimeContext from '../RuntimeContext'; import equals from 'fast-deep-equal'; import { getPresentCell } from '../store/selectors'; import PresentCell from '../PresentCell'; import VScrollBar from '../scroll/VScrollBar'; import classnames from 'classnames'; import * as R from 'rambda'; import { pickPatch } from '../utils'; import { Store } from 'unistore'; import { getAllLoadableRowFlags } from '../scroll/VScrollBar/helper'; import HScrollBar from '../scroll/HScrollBar'; import { getAllLoadableColumnFlags } from '../scroll/HScrollBar/helper'; interface Props {} interface MappedProps { usage: EditorUsage; mode: any; highlightedCells: IStoreState['highlightedCells']; presentCell: ID | null; isActiving: boolean; colDimensions: IColDimensions; rowDimensions: IRowDimensions; // for DataSheet selectionType: ISelectionType | null; selectionCellRange: [ID, ID]; // for selected selectionRowRange: [ID, ID]; selectionColumnRange: [ID, ID]; // for DataSheet.RowGroup rows: IRow[]; columns: IColumn[]; loadableRowFlags: boolean[]; loadableColumnFlags: boolean[]; cells: Record; // for auto scroll to selected scrollX: number; scrollY: number; readyDimensions: boolean; freezeAt: IStoreState['freezeAt']; } interface MappedActions { setScrollXY(xy: { dx: number; dy: number }): { scrollX: number; scrollY: number }; } // 整个Sheet的外部容器 class SpreadSheet extends React.Component { static contextType = RuntimeContext; context!: React.ContextType; constructor(props: Props & MappedProps & MappedActions) { super(props); this.handleWheel = this.handleWheel.bind(this); } shouldComponentUpdate(nextProps: Props & MappedProps) { return !equals(nextProps, this.props); } handleWheel(e: React.WheelEvent) { if (this.props.freezeAt.i >= 0) { this.props.setScrollXY({ dx: e.deltaX, dy: e.deltaY }); // 当滚动后, 对于滚出来的新行, 可能存在重算的需求 setTimeout(() => { this.context!.setSheetDimensions(); }, 0); } } render() { console.log('spreadSheet render'); const { usage, mode, isActiving, highlightedCells, presentCell, selectionType, selectionCellRange, rows, columns, cells, loadableRowFlags, loadableColumnFlags, rowDimensions, colDimensions, scrollX, scrollY, readyDimensions, freezeAt, } = this.props; const showPresentCell = usage === 'editor' && presentCell; const showSelected = fsmPred.isSelecting(mode); const presentCellKey = '' + presentCell!; console.log('scrollYYY', scrollY); return (
{showPresentCell && ( )} {showSelected && } {highlightedCells.length > 0 && ( )}
{freezeAt.i >= 0 && ( )} {freezeAt.j >= 0 && ( )}
); } } const mapState = (state: IStoreState, props: Props): MappedProps => { return { usage: state.usage, mode: state.mode, highlightedCells: state.highlightedCells, presentCell: getPresentCell(state), isActiving: !!state.isActiving, // for DataSheet selectionType: state.selectionType, selectionCellRange: state.selectedCellRange, // for selected, 必须有, 否则不会 re_render selectionRowRange: state.selectedRowRange, selectionColumnRange: state.selectedColumnRange, // for DataSheet.RowGroup rows: state.rows, columns: state.columns, loadableRowFlags: getAllLoadableRowFlags(state), loadableColumnFlags: getAllLoadableColumnFlags(state), cells: state.cells, colDimensions: state.colDimensions, rowDimensions: state.rowDimensions, scrollX: state.scrollX, scrollY: state.scrollY, readyDimensions: !!state.readyDimensions, freezeAt: state.freezeAt, }; }; const actions = (store: Store) => ({ setScrollXY: (state: IStoreState, { dx, dy }: { dx: number; dy: number }) => { let scrollX = Math.max(state.scrollX + dx, 0); let scrollY = Math.max(state.scrollY + dy, 0); const result = pickPatch(store.getState(), { scrollX, scrollY, }); // return R.isEmpty(result) ? null : { ...result, readyDimensions: true }; // 这里无论如何都应该返回readyDimensions:false // 原因: 有时滚动发生了, 但未满1格, 所以rowDimensions并未变化, 然后滚动完成后, ReadyDimensions 仍为true // 这将导致selected / presentcell 不会显示 return { ...result, readyDimensions: false }; }, }); export default connect( mapState, actions, )(SpreadSheet);