massive performance wins

This commit is contained in:
Dylan Vorster
2019-07-29 00:40:22 +02:00
parent b324154eff
commit 61c6d4b161
7 changed files with 57 additions and 82 deletions

View File

@@ -36,8 +36,6 @@ export class DiagramEngine extends BaseObserver<DiagramEngineListener> {
diagramModel: DiagramModel;
canvas: HTMLDivElement;
paintableWidgets: {};
linksThatHaveInitiallyRendered: {};
maxNumberPointsPerLink: number;
constructor() {
@@ -70,7 +68,6 @@ export class DiagramEngine extends BaseObserver<DiagramEngineListener> {
setup(this.actionFactories);
this.canvas = null;
this.paintableWidgets = null;
// this.linksThatHaveInitiallyRendered = {};
}
@@ -82,10 +79,6 @@ export class DiagramEngine extends BaseObserver<DiagramEngineListener> {
});
}
clearRepaintEntities() {
this.paintableWidgets = null;
}
/**
* Gets a model and element under the mouse cursor
*/
@@ -133,26 +126,6 @@ export class DiagramEngine extends BaseObserver<DiagramEngineListener> {
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<DiagramEngineListener> {
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<DiagramEngineListener> {
setDiagramModel(model: DiagramModel) {
this.diagramModel = model;
this.recalculatePortsVisually();
}
getDiagramModel(): DiagramModel {

View File

@@ -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());
}
}

View File

@@ -124,7 +124,6 @@ export class DiagramWidget extends BaseWidget<DiagramProps, DiagramState> {
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<DiagramProps, DiagramState> {
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<DiagramProps, DiagramState> {
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) {

View File

@@ -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<LinkProps, LinkState> {
//generate links
return (
<g>
{React.cloneElement(this.props.diagramEngine.generateWidgetForLink(link), {
pointAdded: this.props.pointAdded
})}
{_.map(this.props.link.getLabels(), (labelModel, index) => {
return <LabelWidget engine={this.props.diagramEngine} label={labelModel} index={index} />;
})}
</g>
<PeformanceWidget serialized={this.props.link.serialize()}>
{() => {
return (
<g>
{React.cloneElement(this.props.diagramEngine.generateWidgetForLink(link), {
pointAdded: this.props.pointAdded
})}
{_.map(this.props.link.getLabels(), (labelModel, index) => {
return <LabelWidget engine={this.props.diagramEngine} label={labelModel} index={index} />;
})}
</g>
);
}}
</PeformanceWidget>
);
}
}

View File

@@ -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<NodeProps> {
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<NodeProps> {
render() {
return (
<div
ref={this.ref}
{...this.getProps()}
data-nodeid={this.props.node.getID()}
style={{
top: this.props.node.getY(),
left: this.props.node.getX()
}}>
{this.props.diagramEngine.generateWidgetForNode(this.props.node)}
</div>
<PeformanceWidget serialized={this.props.node.serialize()}>
{() => {
return (
<div
ref={this.ref}
{...this.getProps()}
data-nodeid={this.props.node.getID()}
style={{
top: this.props.node.getY(),
left: this.props.node.getX()
}}>
{this.props.diagramEngine.generateWidgetForNode(this.props.node)}
</div>
);
}}
</PeformanceWidget>
);
}
}

View File

@@ -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<PeformanceWidgetProps, PeformanceWidgetState> {
shouldComponentUpdate(
nextProps: Readonly<PeformanceWidgetProps>,
nextState: Readonly<PeformanceWidgetState>,
nextContext: any
): boolean {
return !_.isEqual(this.props.serialized, nextProps.serialized);
}
render() {
return this.props.children();
}
}

View File

@@ -14,6 +14,7 @@ namespace S {
font-size: 12px;
padding: 4px 8px;
font-family: sans-serif;
user-select: none;
`;
}