Skip to content

Commit

Permalink
integration with cottontail, wip
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanbatic committed Oct 12, 2017
1 parent 8188371 commit 9e58d13
Show file tree
Hide file tree
Showing 11 changed files with 336 additions and 209 deletions.
5 changes: 5 additions & 0 deletions index.ts
@@ -0,0 +1,5 @@
export * from "./src/graph/workflow";
export * from "./src/plugins/port-drag/port-drag";
export * from "./src/plugins/arrange/arrange";
export * from "./src/plugins/edge-hover/edge-hover";
export * from "./src/plugins/node-move/node-move";
131 changes: 131 additions & 0 deletions src/behaviors/edge-panning.ts
@@ -0,0 +1,131 @@
import {Workflow} from "../";

export class EdgePanning {

private movementSpeed = 10;

private panAnimationFrame;
private workflow: Workflow;

private scrollMargin = 100;
private collision = {x: 0, y: 0};
private viewportClientRect: ClientRect;
private handoff: { sdx: number, sdy: number };
private panningCallback = (sdx: number, sdy: number) => void 0;

constructor(workflow: Workflow, config = {
scrollMargin: 100
}) {
this.workflow = workflow;
Object.assign(this, config);

this.viewportClientRect = this.workflow.svgRoot.getBoundingClientRect();
}

triggerCollisionDetection(x: number, y: number, sdx: number, sdy: number, callback) {
const collision = {x: 0, y: 0};
this.handoff = {sdx, sdy};
this.panningCallback = callback;

let {left, right, top, bottom} = this.viewportClientRect;

left = left + this.scrollMargin;
right = right - this.scrollMargin;
top = top + this.scrollMargin;
bottom = bottom - this.scrollMargin;

if (x < left) {
collision.x = x - left
} else if (x > right) {
collision.x = x - right;
}

if (y < top) {
collision.y = y - top;
} else if (y > bottom) {
collision.y = y - bottom;
}

if (
Math.sign(collision.x) !== Math.sign(this.collision.x)
|| Math.sign(collision.y) !== Math.sign(this.collision.y)
) {
const previous = this.collision;
this.collision = collision;
this.onBoundaryCollisionChange(collision, previous);
}
}

/**
* Triggered when {@link triggerCollisionDetection} determines that collision properties have changed.
*/
private onBoundaryCollisionChange(current: { x: number, y: number }, previous: { x: number, y: number }): void {

this.stop();

if (current.x === 0 && current.y === 0) {
return;
}

this.start(this.collision, this.handoff);
}

private start(direction: { x: number, y: number },
handoffDiff: { sdx: number, sdy: number }) {

let startTimestamp: number;

const scale = this.workflow.scale;
const matrix = this.workflow.workflow.transform.baseVal.getItem(0).matrix;
const sixtyFPS = 16.6666;

const onFrame = (timestamp: number) => {

const frameDeltaTime = timestamp - (startTimestamp || timestamp);
startTimestamp = timestamp;

// We need to stop the animation at some point
// It should be stopped when there is no animation frame ID anymore,
// which means that stopScroll() was called
// However, don't do that if we haven't made the first move yet, which is a situation when ∆t is 0
if (frameDeltaTime !== 0 && !this.panAnimationFrame) {
startTimestamp = undefined;
return;
}

const moveX = Math.sign(direction.x) * this.movementSpeed * frameDeltaTime / sixtyFPS;
const moveY = Math.sign(direction.y) * this.movementSpeed * frameDeltaTime / sixtyFPS;

matrix.e -= moveX;
matrix.f -= moveY;

const xDiff = moveX / scale;
const yDiff = moveY / scale;

console.log("Handoff", handoffDiff);

const sdx = handoffDiff.sdx + xDiff;
const sdy = handoffDiff.sdy + yDiff;


this.panningCallback(sdx, sdy);

// this.translateNodeBy(this.movingNode, xDiff, yDiff);
//
// this.sdx += xDiff;
// this.sdy += yDiff;
//
// this.redrawEdges(this.sdx, this.sdy);

this.panAnimationFrame = window.requestAnimationFrame(onFrame);
};

this.panAnimationFrame = window.requestAnimationFrame(onFrame);
}

private stop() {
window.cancelAnimationFrame(this.panAnimationFrame);
this.panAnimationFrame = undefined;
}

}
23 changes: 11 additions & 12 deletions src/graph/graph-node.ts
@@ -1,7 +1,7 @@
import {StepModel, WorkflowInputParameterModel, WorkflowOutputParameterModel} from "cwlts/models";
import {SVGUtils} from "../utils/svg-utils";
import {IOPort} from "./io-port";
import {HtmlUtils} from "../utils/html-utils";
import {SVGUtils} from "../utils/svg-utils";
import {IOPort} from "./io-port";
import {HtmlUtils} from "../utils/html-utils";

export type NodePosition = { x: number, y: number };
export type NodeDataModel = WorkflowInputParameterModel | WorkflowOutputParameterModel | StepModel;
Expand Down Expand Up @@ -68,15 +68,14 @@ export class GraphNode {
label?: string,
in?: any[],
out?: any[],
customProps?: Object
}, x?: number, y?: number): string {

if(x === undefined){
x = ~~ (dataModel.customProps && dataModel.customProps["sbg:x"]);
}
if(y === undefined){
y = ~~ (dataModel.customProps && dataModel.customProps["sbg:y"]);
customProps?: {
"sbg:x"?: number
"sbg:y"?: number
}
}, labelScale = 1): string {

const x = ~~(dataModel.customProps && dataModel.customProps["sbg:x"]);
const y = ~~(dataModel.customProps && dataModel.customProps["sbg:y"]);

let nodeTypeClass = "step";
if (dataModel instanceof WorkflowInputParameterModel) {
Expand Down Expand Up @@ -128,7 +127,7 @@ export class GraphNode {
${GraphNode.makeIconFragment(dataModel)}
</g>
<text transform="matrix(1,0,0,1,0,${radius + 30})" class="title label">${HtmlUtils.escapeHTML(dataModel.label || dataModel.id)}</text>
<text transform="matrix(${labelScale},0,0,${labelScale},0,${radius + 30})" class="title label">${HtmlUtils.escapeHTML(dataModel.label || dataModel.id)}</text>
${inputPortTemplates}
${outputPortTemplates}
</g>
Expand Down

0 comments on commit 9e58d13

Please sign in to comment.