Skip to content

Commit

Permalink
Refactor internalRender wires into Connections and Wire component, ad…
Browse files Browse the repository at this point in the history
…d basic tests
  • Loading branch information
ja0n committed Jun 1, 2021
1 parent b7a98b8 commit 5ca0996
Show file tree
Hide file tree
Showing 19 changed files with 517 additions and 445 deletions.
96 changes: 0 additions & 96 deletions src/BaseWire.js

This file was deleted.

84 changes: 84 additions & 0 deletions src/BaseWire.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { _p } from './utils/points';
import { spliceByIndex } from './utils/dom'
import type { Position } from './types'
import Port from './Port';

type ControlPoint = Port|Position

export default class BaseWire {
controlPoints: ControlPoint[];
_inverted: Boolean = false;
custom: Boolean = false;
_el: SVGElement;

constructor ( config ) {
const { controlPoints, render } = config;
this.controlPoints = controlPoints || [];
this._inverted = false;
// this.renderInstance = render;
this.custom = false;

return this;
}

getControlPoints () {
const [head, ...tail] = this.controlPoints;
return [head, tail.pop()];
}

getPorts () {
return this.getControlPoints().filter(<(v) => v is Port>(v => v instanceof Port));
}

addControlPoints (...controlPoints: ControlPoint[]) {
this.controlPoints = [...this.controlPoints, ...controlPoints];
}

setTarget (value) {
const [head, ...tail] = this.controlPoints;
this.controlPoints = [head, value];
}

setupInstance (ref: SVGElement) {
this._el = ref;
this._el['type'] = 'wire';
this._el['wrapper'] = this;
}

getNodes () {
const [sourcePort, targetPort] = this.getPorts() as Port[];
return [sourcePort?.node, targetPort?.node]
}

seal() {
const [sourcePort, targetPort] = this.getPorts();

if (sourcePort?.direction == targetPort?.direction)
return false;

const canAttach = sourcePort.attach(targetPort);

if (canAttach) {
sourcePort.node.wires.push(this);
targetPort.node.wires.push(this);
}

return canAttach;
}

delete () {
const [sourcePort, targetPort] = this.getPorts();
spliceByIndex( sourcePort.node.wires, this );
spliceByIndex( targetPort.node.wires, this );
sourcePort.dettach(targetPort);
}

getPointTranslated (point, offset = { x: 0, y: 0 }, zoom = 1) {
const vOffset = _p.multiply(offset, zoom);
return _p.add(point, vOffset);
}

render (offset, zoom) {
return null;
}
}
8 changes: 3 additions & 5 deletions src/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import _isNil from 'lodash/isNil';
import set from 'lodash/set';
import forEach from 'lodash/forEach';
import Port from './Port'
import Wire from './Wire'
import BaseWire from './BaseWire';

import { SVGContainer } from './blockBuilder';
import { getParentSvg } from './utils/dom';
Expand Down Expand Up @@ -66,7 +66,7 @@ export default class Node {
_states: { dragging: boolean };
x: number;
y: number;
wires: Wire[];
wires: BaseWire[];
behavior: Function; // run
cfg: NodeConfig; // config
gui: GuiConfig; // inputsConfig
Expand Down Expand Up @@ -121,12 +121,10 @@ export default class Node {
delete () {
for (let wire of [...this.wires])
wire.delete();

this._el.parentNode.removeChild(this._el);
}

updateWires (offset, zoom) {
this.wires.forEach( wire => wire.render(offset, zoom) );
// this.wires.forEach( wire => wire.render(offset, zoom) );
}

getValue (getNode, context, id?) {
Expand Down
4 changes: 2 additions & 2 deletions src/Port.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ export default class Port {
return this._el.getAttribute(key);
}

getPoint (zoom = 1) {
return _p.add(_p.multiply(this.node, zoom), this);
getPoint (offset = { x: 0, y: 0 }, zoom = 1) {
return _p.add(_p.multiply(this.node, zoom), _p.multiply(offset, zoom), this);
}

isCompatible (to: Port) {
Expand Down
102 changes: 47 additions & 55 deletions src/Render.js → src/Render.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,57 @@
import React from 'react';
import ReactDOM from 'react-dom';
import _throttle from 'lodash/throttle';

import BaseWire from './BaseWire';
import Sticky from './Sticky';
import Wire from './Wire';
import { createElement } from './utils/dom';
import { registerEvents } from './domEventHandlers'
import { NodeGraph } from './react/components';
import { registerEvents } from './eventHandlers'
import { _p } from './utils/points';
import { Offset, Position, TargetElement, TargetWrappers, Zoom } from './types';

const defaultConfig = { width: 800, height: 600 };
export type Config = typeof defaultConfig & { wrapper: Sticky };

type MouseDownContext = Position & { offset?: Offset; wrapper?: Position; barePos?: Position; mouse?: Position; };
type TemporaryContext = { wire?: BaseWire; lastZoomTime?: number; mouseDown?: MouseDownContext; };

// TODO:
// change id argument approach, use 'element' from config
// move reactDom outside
export default class Render {
constructor (id, config) {
_svg: SVGElement & { type?: string };
zoom: Zoom = 1;
offset: Offset = { x: 0, y: 0 };
disableZoom = false;
disableDragging = false;
internalRender = true;
gridSize = 20;
gridColor = 'grey';
backgroundColor = '#CCCCCC75';
config: Config;
lastSelected?: TargetWrappers;
dragging?: TargetElement;
_state: null | string;
_wires: BaseWire[];
_aux: TemporaryContext;
react?: React.Component;

constructor (config) {
this.config = { ...defaultConfig, ...config };
this._aux = {};
this._state = null;
this._wires = [];
this.offset = { x: 0, y: 0 };
this.zoom = 1;
this.disableZoom = false;
this.disableDragging = false;
this.internalRender = true;
this.gridSize = 20;
this.gridColor = 'grey';
this.backgroundColor = '#CCCCCC75';

const element = document.getElementById(id);
if (element) {
this.reactDOM(element);
}
this.lastSelected = null;
this.dragging = null;

this._p = _p;
// this._p = _p;

return this;
}

get selectedWire() {
return this.lastSelected instanceof BaseWire ? this.lastSelected : null;
}

getConnections () {
const connections = [...this._wires];
const { wire } = this._aux;
Expand All @@ -52,29 +67,10 @@ export default class Render {
registerEvents.call(this);
}

reactDOM (element) {
const { wrapper, Component } = this.config;
const svg = createElement('svg', { class: 'svg-content', preserveAspectRatio: "xMidYMid meet" });
this.loadContainer(svg);

element.classList.add('sticky__canvas');
element.appendChild(this._svg);

ReactDOM.render(
<NodeGraph
ref={ref => { this.react = ref }}
getNodes={() => wrapper.nodes}
getOffset={() => this.offset}
getZoom={() => this.zoom}
/>,
svg
);
}

loadContainer (svg) {
loadContainer (svg: SVGElement) {
const { width, height } = this.config;
this._svg = svg;
svg.type = 'container';
this._svg.type = 'container';
this.matchViewBox();
this.setCanvasSize({ width, height });
this.registerEvents();
Expand Down Expand Up @@ -104,8 +100,8 @@ export default class Render {

startDrag (port) {
this.setState('dragging');
this._aux['wire'] = wire;
this.addElement(wire._el);
// this._aux['wire'] = wire;
// this.addElement(wire._el);
}

startAttach (port) {
Expand All @@ -116,7 +112,7 @@ export default class Render {
this._aux['wire'] = wire;

if (this.internalRender) {
this.addElement(wire._el);
// this.addElement(wire._el);
}
}

Expand Down Expand Up @@ -146,25 +142,19 @@ export default class Render {
return true;
}

removeWire (wire) {
removeWire (wire: BaseWire) {
const index = this._wires.indexOf(wire);
if (index == -1) return;
this._wires.splice(index, 1);
}

renderWires () {
this._wires.forEach(wire => {
wire.render(this.offset, this.zoom);
});
this.forceUpdate();
if (index == -1) return null;
const removed = this._wires.splice(index, 1)[0];
removed.delete();
return removed;
}

getGridStyle () {
const { offset, zoom, gridSize, gridColor, backgroundColor } = this;
const zOffset = _p.multiply(offset, zoom);
const zGridSize = gridSize * zoom;
const lineWidth = `${parseInt(_p.clamp(1, 1 * zoom, 10))}px`;
console.info('getGridStyle - lineWidthPx', lineWidth);
const lineWidth = `${parseInt(_p.clamp(1, 1 * zoom, 10).toString())}px`;

return {
backgroundColor,
Expand Down Expand Up @@ -225,6 +215,8 @@ export default class Render {
this.react.forceUpdate();
}

throttleUpdate = _throttle(this.forceUpdate, 1)

setZoom (value) {
const cameraTarget = this.getCenterPoint();
this.zoom = value;
Expand Down
Loading

0 comments on commit 5ca0996

Please sign in to comment.