From 61c6d4b1614eb033439b0b2cddcaf5e1f48fe511 Mon Sep 17 00:00:00 2001 From: Dylan Vorster Date: Mon, 29 Jul 2019 00:40:22 +0200 Subject: [PATCH] massive performance wins --- lib-core/src/DiagramEngine.ts | 41 ------------------- .../src/actions/move-items/MoveItemsAction.ts | 12 ------ lib-core/src/widgets/DiagramWidget.tsx | 8 +--- lib-core/src/widgets/LinkWidget.tsx | 23 +++++++---- lib-core/src/widgets/NodeWidget.tsx | 31 +++++++------- lib-core/src/widgets/PeformanceWidget.tsx | 23 +++++++++++ lib-defaults/src/label/DefaultLabelWidget.tsx | 1 + 7 files changed, 57 insertions(+), 82 deletions(-) create mode 100644 lib-core/src/widgets/PeformanceWidget.tsx diff --git a/lib-core/src/DiagramEngine.ts b/lib-core/src/DiagramEngine.ts index dd1ce7b..e5ca8dc 100644 --- a/lib-core/src/DiagramEngine.ts +++ b/lib-core/src/DiagramEngine.ts @@ -36,8 +36,6 @@ export class DiagramEngine extends BaseObserver { diagramModel: DiagramModel; canvas: HTMLDivElement; - paintableWidgets: {}; - linksThatHaveInitiallyRendered: {}; maxNumberPointsPerLink: number; constructor() { @@ -70,7 +68,6 @@ export class DiagramEngine extends BaseObserver { setup(this.actionFactories); this.canvas = null; - this.paintableWidgets = null; // this.linksThatHaveInitiallyRendered = {}; } @@ -82,10 +79,6 @@ export class DiagramEngine extends BaseObserver { }); } - clearRepaintEntities() { - this.paintableWidgets = null; - } - /** * Gets a model and element under the mouse cursor */ @@ -133,26 +126,6 @@ export class DiagramEngine extends BaseObserver { return null; } - enableRepaintEntities(entities: BaseModel[]) { - this.paintableWidgets = {}; - entities.forEach(entity => { - //if a node is requested to repaint, add all of its links - if (entity instanceof NodeModel) { - _.forEach(entity.getPorts(), port => { - _.forEach(port.getLinks(), link => { - this.paintableWidgets[link.getID()] = true; - }); - }); - } - - if (entity instanceof PointModel) { - this.paintableWidgets[entity.getLink().getID()] = true; - } - - this.paintableWidgets[entity.getID()] = true; - }); - } - /** * Checks to see if a model is locked by running through * its parents to see if they are locked first @@ -166,19 +139,6 @@ export class DiagramEngine extends BaseObserver { return model.isLocked(); } - recalculatePortsVisually() { - this.linksThatHaveInitiallyRendered = {}; - } - - canEntityRepaint(baseModel: BaseModel) { - //no rules applied, allow repaint - if (this.paintableWidgets === null) { - return true; - } - - return this.paintableWidgets[baseModel.getID()] !== undefined; - } - setCanvas(canvas?: HTMLDivElement) { if (this.canvas !== canvas) { this.canvas = canvas; @@ -190,7 +150,6 @@ export class DiagramEngine extends BaseObserver { setDiagramModel(model: DiagramModel) { this.diagramModel = model; - this.recalculatePortsVisually(); } getDiagramModel(): DiagramModel { diff --git a/lib-core/src/actions/move-items/MoveItemsAction.ts b/lib-core/src/actions/move-items/MoveItemsAction.ts index dbea2e0..155b975 100644 --- a/lib-core/src/actions/move-items/MoveItemsAction.ts +++ b/lib-core/src/actions/move-items/MoveItemsAction.ts @@ -33,14 +33,6 @@ export class MoveItemsAction extends AbstractMouseAction { this.model.getGridPosition(model.initialX + amountX / amountZoom), this.model.getGridPosition(model.initialY + amountY / amountZoom) ); - - if (model.model instanceof NodeModel) { - // update port coordinates as well - _.forEach(model.model.getPorts(), port => { - const portCoords = this.engine.getPortCoords(port); - port.updateCoords(portCoords); - }); - } } else if (model.model instanceof PointModel) { // we want points that are connected to ports, to not necessarily snap to grid // this stuff needs to be pixel perfect, dont touch it @@ -89,7 +81,6 @@ export class MoveItemsAction extends AbstractMouseAction { link.setTargetPort(element.model); link.getLastPoint().setPosition(this.engine.getPortCenter(element.model)); } - delete this.engine.linksThatHaveInitiallyRendered[link.getID()]; } }); @@ -134,8 +125,6 @@ export class MoveItemsAction extends AbstractMouseAction { } } }); - - this.engine.clearRepaintEntities(); } fireMouseDown(event: ActionFactoryActivationEvent) { @@ -184,6 +173,5 @@ export class MoveItemsAction extends AbstractMouseAction { initialY: item.getY() }; }); - this.engine.enableRepaintEntities(this.model.getSelectedItems()); } } diff --git a/lib-core/src/widgets/DiagramWidget.tsx b/lib-core/src/widgets/DiagramWidget.tsx index b8ead0f..d9bd8d9 100644 --- a/lib-core/src/widgets/DiagramWidget.tsx +++ b/lib-core/src/widgets/DiagramWidget.tsx @@ -124,7 +124,6 @@ export class DiagramWidget extends BaseWidget { if (this.state.action && this.state.action instanceof AbstractMouseAction) { this.state.action.fireMouseUp(event); } - this.props.diagramEngine.clearRepaintEntities(); this.stopFiringAction(); document.removeEventListener('mousemove', this.onMouseMove); document.removeEventListener('mouseup', this.onMouseUp); @@ -171,7 +170,6 @@ export class DiagramWidget extends BaseWidget { getActionForEvent(event: MouseEvent): AbstractAction { event.persist(); - this.props.diagramEngine.clearRepaintEntities(); const { diagramEngine } = this.props; const model = diagramEngine.getMouseElement(event); @@ -238,14 +236,10 @@ export class DiagramWidget extends BaseWidget { diagramModel.getOffsetY() - heightDiff * yFactor ); - diagramEngine.enableRepaintEntities([]); - this.forceUpdate(() => { - this.props.diagramEngine.clearRepaintEntities(); - }); + this.forceUpdate(); } }} onMouseDown={event => { - diagramEngine.clearRepaintEntities(); // try and get an action for this event const action = this.getActionForEvent(event); if (action) { diff --git a/lib-core/src/widgets/LinkWidget.tsx b/lib-core/src/widgets/LinkWidget.tsx index f0d2fb1..9bf96a6 100644 --- a/lib-core/src/widgets/LinkWidget.tsx +++ b/lib-core/src/widgets/LinkWidget.tsx @@ -9,6 +9,7 @@ import { PortModel } from '../models/PortModel'; import { MouseEvent } from 'react'; import * as _ from 'lodash'; import { LabelWidget } from './LabelWidget'; +import { PeformanceWidget } from './PeformanceWidget'; export interface LinkProps { link: LinkModel; @@ -98,14 +99,20 @@ export class LinkWidget extends React.Component { //generate links return ( - - {React.cloneElement(this.props.diagramEngine.generateWidgetForLink(link), { - pointAdded: this.props.pointAdded - })} - {_.map(this.props.link.getLabels(), (labelModel, index) => { - return ; - })} - + + {() => { + return ( + + {React.cloneElement(this.props.diagramEngine.generateWidgetForLink(link), { + pointAdded: this.props.pointAdded + })} + {_.map(this.props.link.getLabels(), (labelModel, index) => { + return ; + })} + + ); + }} + ); } } diff --git a/lib-core/src/widgets/NodeWidget.tsx b/lib-core/src/widgets/NodeWidget.tsx index 5d37597..90863eb 100644 --- a/lib-core/src/widgets/NodeWidget.tsx +++ b/lib-core/src/widgets/NodeWidget.tsx @@ -6,6 +6,7 @@ import { BaseWidget, BaseWidgetProps } from './BaseWidget'; import { BaseEntityEvent } from '../core-models/BaseEntity'; import { BaseModel } from '../core-models/BaseModel'; import { ListenerHandle } from '../core/BaseObserver'; +import { PeformanceWidget } from './PeformanceWidget'; export interface NodeProps extends BaseWidgetProps { node: NodeModel; @@ -23,10 +24,6 @@ export class NodeWidget extends BaseWidget { this.ref = React.createRef(); } - shouldComponentUpdate() { - return this.props.diagramEngine.canEntityRepaint(this.props.node); - } - getClassName() { return 'node ' + super.getClassName() + (this.props.node.isSelected() ? this.bem('--selected') : ''); } @@ -67,16 +64,22 @@ export class NodeWidget extends BaseWidget { render() { return ( -
- {this.props.diagramEngine.generateWidgetForNode(this.props.node)} -
+ + {() => { + return ( +
+ {this.props.diagramEngine.generateWidgetForNode(this.props.node)} +
+ ); + }} +
); } } diff --git a/lib-core/src/widgets/PeformanceWidget.tsx b/lib-core/src/widgets/PeformanceWidget.tsx new file mode 100644 index 0000000..4610862 --- /dev/null +++ b/lib-core/src/widgets/PeformanceWidget.tsx @@ -0,0 +1,23 @@ +import * as React from 'react'; +import * as _ from 'lodash'; + +export interface PeformanceWidgetProps { + children: () => JSX.Element; + serialized: object; +} + +export interface PeformanceWidgetState {} + +export class PeformanceWidget extends React.Component { + shouldComponentUpdate( + nextProps: Readonly, + nextState: Readonly, + nextContext: any + ): boolean { + return !_.isEqual(this.props.serialized, nextProps.serialized); + } + + render() { + return this.props.children(); + } +} diff --git a/lib-defaults/src/label/DefaultLabelWidget.tsx b/lib-defaults/src/label/DefaultLabelWidget.tsx index 2b7f7c9..56edfe1 100644 --- a/lib-defaults/src/label/DefaultLabelWidget.tsx +++ b/lib-defaults/src/label/DefaultLabelWidget.tsx @@ -14,6 +14,7 @@ namespace S { font-size: 12px; padding: 4px 8px; font-family: sans-serif; + user-select: none; `; }