Skip to content

Commit

Permalink
simplified port position saving
Browse files Browse the repository at this point in the history
  • Loading branch information
M-Wicenec committed Oct 13, 2023
1 parent 3dd9468 commit ebce6fb
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 32 deletions.
31 changes: 9 additions & 22 deletions src/Field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@ export class Field {
private positional : ko.Observable<boolean>;
private keyAttribute : ko.Observable<boolean>;

private inputX : number;
private inputY : number;
private outputX : number;
private outputY : number;
private x : number;
private y : number;

// port-specific attributes
private id : ko.Observable<string>;
Expand All @@ -40,10 +38,8 @@ export class Field {
this.positional = ko.observable(positional);
this.keyAttribute = ko.observable(keyAttribute);

this.inputX = 0;
this.inputY = 0;
this.outputX = 0;
this.outputY = 0;
this.x = 0;
this.y = 0;

this.id = ko.observable(id);
this.parameterType = ko.observable(parameterType);
Expand Down Expand Up @@ -100,22 +96,13 @@ export class Field {
return this.description() == "" ? "No description available" + " (" + this.type() + ", default value:'" + this.defaultValue() + "')" : this.description() + " (" + this.type() + ", default value:'" + this.defaultValue() + "')";
}, this);

getInputPosition = () : {x:number, y:number} => {
return {x: this.inputX, y: this.inputY};
getPortPosition = () : {x:number, y:number} => {
return {x: this.x, y: this.y};
}

getOutputPosition = () : {x:number, y:number} => {
return {x: this.outputX, y: this.outputY};
}

setInputPosition = (x: number, y: number) : void => {
this.inputX = x;
this.inputY = y;
}

setOutputPosition = (x: number, y: number) : void => {
this.outputX = x;
this.outputY = y;
setPortPosition = (x: number, y: number) : void => {
this.x = x;
this.y = y;
}

isReadonly = () : boolean => {
Expand Down
142 changes: 132 additions & 10 deletions src/GraphRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ ko.bindingHandlers.graphRendererPortPosition = {

const data = ko.utils.unwrapObservable(valueAccessor()).data;
const dataType: string = ko.utils.unwrapObservable(valueAccessor()).type;
const portOnEmbeddedApp = false //used to identify when we are calculating the port position for a port on an embedded application

// determine the 'node' and 'field' attributes (for this way of using this binding)
let node : Node
Expand Down Expand Up @@ -158,10 +157,10 @@ ko.bindingHandlers.graphRendererPortPosition = {

//for branch nodes the ports are inset from the outer radius a little bit in their design
let nodeRadius = node.getRadius()
if(portOnEmbeddedApp){
// if we are working with ports of an embedded app, we need to use the parent construct to calculate the angle, but we want to use the radius of the embedded app to place the port
nodeRadius = eagle.logicalGraph().findNodeByKeyQuiet(data.getNodeKey()).getRadius()
}
// if(portOnEmbeddedApp){
// // if we are working with ports of an embedded app, we need to use the parent construct to calculate the angle, but we want to use the radius of the embedded app to place the port
// nodeRadius = eagle.logicalGraph().findNodeByKeyQuiet(data.getNodeKey()).getRadius()
// }

// determine port position
const currentNodePos = node.getPosition();
Expand Down Expand Up @@ -206,9 +205,9 @@ ko.bindingHandlers.graphRendererPortPosition = {
}

if (dataType === 'inputPort'){
field.setInputPosition(portPosition.x, portPosition.y);
field.setPortPosition(portPosition.x, portPosition.y);
} else if (dataType === 'outputPort'){
field.setOutputPosition(portPosition.x, portPosition.y);
field.setPortPosition(portPosition.x, portPosition.y);
}

let x
Expand Down Expand Up @@ -251,9 +250,132 @@ export class GraphRenderer {
static nodeDragElement : any = null
// static isDraggingPortValid : Eagle.LinkValid = Eagle.LinkValid.Unknown;


static graphMousePos = { x: -1, y: -1 };

static getPortPositions(node: Node,field:Field,dataType:string) : void {
//the update function is called initially and then whenever a change to a utilised observable occurs
const eagle : Eagle = Eagle.getInstance();

const portOnEmbeddedApp = false //used to identify when we are calculating the port position for a port on an embedded application

// clearing the saved port angles array
node.resetPortAngles()

// determine all the adjacent nodes
const adjacentNodes: Node[] = [];
let connectedField:boolean=false;

switch(dataType){
case 'comment':
const adjacentNode: Node = eagle.logicalGraph().findNodeByKeyQuiet(node.getSubjectKey());

if (adjacentNode === null){
console.warn("Could not find adjacentNode for comment with subjectKey", node.getSubjectKey());
return;
}

adjacentNodes.push(adjacentNode);
break;

case 'inputApp':
case 'inputPort':
for(const edge of eagle.logicalGraph().getEdges()){
if(field.getId()===edge.getDestPortId()){
const adjacentNode: Node = eagle.logicalGraph().findNodeByKeyQuiet(edge.getSrcNodeKey());
connectedField=true
adjacentNodes.push(adjacentNode);
continue;
}
}
break;

case 'outputApp':
case 'outputPort':
for(const edge of eagle.logicalGraph().getEdges()){
if(field.getId()===edge.getSrcPortId()){
const adjacentNode: Node = eagle.logicalGraph().findNodeByKeyQuiet(edge.getDestNodeKey());
connectedField=true
adjacentNodes.push(adjacentNode);
continue;
}
}
break;
}

//for branch nodes the ports are inset from the outer radius a little bit in their design
let nodeRadius = node.getRadius()
if(portOnEmbeddedApp){
// if we are working with ports of an embedded app, we need to use the parent construct to calculate the angle, but we want to use the radius of the embedded app to place the port
nodeRadius = eagle.logicalGraph().findNodeByKeyQuiet(field.getNodeKey()).getRadius()
}

// determine port position
const currentNodePos = node.getPosition();
let portPosition;

if(connectedField || dataType === 'comment'){

// calculate angles to all adjacent nodes
const angles: number[] = [];
for (const adjacentNode of adjacentNodes){
const adjacentNodePos = adjacentNode.getPosition()
const edgeAngle = GraphRenderer.calculateConnectionAngle(currentNodePos, adjacentNodePos)
angles.push(edgeAngle);
}

// average the angles
const averageAngle = GraphRenderer.averageAngles(angles);

node.addPortAngle(averageAngle);
portPosition = GraphRenderer.calculatePortPos(averageAngle, nodeRadius, nodeRadius)
}else{
// find a default position for the port when not connected
switch (dataType){
case 'inputApp':
case 'inputPort':
portPosition=GraphRenderer.calculatePortPos(Math.PI, nodeRadius, nodeRadius)
break;
case 'outputApp':
case 'outputPort':
portPosition=GraphRenderer.calculatePortPos(0, nodeRadius, nodeRadius)
break;
default:
console.warn("disconnected field with dataType:", dataType);
portPosition=GraphRenderer.calculatePortPos(Math.PI/2, nodeRadius, nodeRadius)
break;
}
}

//a little 1px reduction is needed to center ports for some reason
if(!node.isBranch()){
portPosition = {x:portPosition.x-1,y:portPosition.y-1}
}

if (dataType === 'inputPort'){
field.setPortPosition(portPosition.x, portPosition.y);
} else if (dataType === 'outputPort'){
field.setPortPosition(portPosition.x, portPosition.y);
}

let x
let y

if (dataType === 'inputApp' || dataType === 'outputApp'){
//we are saving the embedded application's position data here using the offset we calculated
const newPos = {x: node.getPosition().x-nodeRadius+portPosition.x, y:node.getPosition().y-nodeRadius+portPosition.y}
node.setPosition(newPos.x,newPos.y)
portPosition = {x:portPosition.x-nodeRadius,y:portPosition.y-nodeRadius}
x = portPosition.x
y = portPosition.y
}else{

x = portPosition.x + currentNodePos.x + eagle.globalOffsetX() - nodeRadius
y = portPosition.y + currentNodePos.y + eagle.globalOffsetY() - nodeRadius
}

//applying the offset to the element
// $(element).css({'top':y+'px','left':x+'px'})
}

static averageAngles(angles: number[]) : number {
let x: number = 0;
Expand Down Expand Up @@ -359,12 +481,12 @@ export class GraphRenderer {
let srcPortOffset;
let destPortOffset;
if (srcField){
srcPortOffset = srcField.getOutputPosition();
srcPortOffset = srcField.getPortPosition();
} else {
srcPortOffset = GraphRenderer.calculatePortPos(srcPortAngle, srcNodeRadius, srcNodeRadius);
}
if (destField){
destPortOffset = destField.getInputPosition();
destPortOffset = destField.getPortPosition();
} else {
destPortOffset = GraphRenderer.calculatePortPos(destPortAngle, destNodeRadius, destNodeRadius);
}
Expand Down

0 comments on commit ebce6fb

Please sign in to comment.