Skip to content

Commit

Permalink
Merge pull request #820 from ICRAR/eagle-1385
Browse files Browse the repository at this point in the history
Eagle 1385
  • Loading branch information
M-Wicenec authored Feb 13, 2025
2 parents 8f17800 + 751361f commit ec33c39
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 40 deletions.
2 changes: 1 addition & 1 deletion src/EagleConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export class EagleConfig {
// when creating a new construct to enclose a selection, or shrinking a node to enclose its children,
// this is the default margin that should be left on each side
public static readonly CONSTRUCT_MARGIN: number = 30;
public static readonly CONSTRUCT_DRAG_OUT_DISTANCE: number = 200;
public static readonly CONSTRUCT_DRAG_OUT_DISTANCE: number = 100;

// number of spaces used for indenting output JSON, makes everything human-readable
public static readonly JSON_INDENT: number = 4;
Expand Down
98 changes: 59 additions & 39 deletions src/GraphRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,9 @@ export class GraphRenderer {
static dragSelectionHandled : any = ko.observable(true)
static dragSelectionDoubleClick :boolean = false;

static findParent : boolean = false;
static parentTimeout : boolean = false;

//drag selection region globals
static altSelect : boolean = false;
static shiftSelect : boolean = false;
Expand Down Expand Up @@ -1123,9 +1126,7 @@ export class GraphRenderer {

//look for a construct at the current location that we would parent to
//the outermost node is the outermost construct for multiselection
outermostNodes.forEach(function(outerMostNode){
GraphRenderer.lookForParent(outerMostNode)
})
GraphRenderer.lookForParent()
} else if(GraphRenderer.isDraggingSelectionRegion){

//update selection region position then draw the rectangle
Expand Down Expand Up @@ -1266,50 +1267,65 @@ export class GraphRenderer {
})
}

static lookForParent(outerMostNode:Node) : void {
static lookForParent() : void {
const eagle = Eagle.getInstance()
// remember node parent from before things change
const oldParent: Node = eagle.logicalGraph().findNodeByIdQuiet(outerMostNode.getParentId());
const outermostNodes : Node[] = eagle.getOutermostSelectedNodes()

for (const outermostNode of outermostNodes){
const oldParent: Node = eagle.logicalGraph().findNodeByIdQuiet(outermostNode.getParentId());
let parentingSuccessful = false; //if the detected parent of one node in the selection changes, we assign the new parent to the whole selection and exit this loop

// keep track of whether we would update any node parents
const allowGraphEditing = Setting.findValue(Setting.ALLOW_GRAPH_EDITING);
//construct resizing
if(outerMostNode.getParentId() != null && oldParent.getRadius()>GraphRenderer.NodeParentRadiusPreDrag+EagleConfig.CONSTRUCT_DRAG_OUT_DISTANCE){
oldParent.setRadius(GraphRenderer.NodeParentRadiusPreDrag) //HERE
outerMostNode.setParentId(null)
}
// the parent construct is only allowed to grow by the amout specified(eagleConfig.construct_drag_out_distance) before allowing its children to escape
if(outermostNode.getParentId() != null && oldParent.getRadius()>GraphRenderer.NodeParentRadiusPreDrag+EagleConfig.CONSTRUCT_DRAG_OUT_DISTANCE){
$('#'+oldParent.getId()).addClass('transition')
GraphRenderer.parentSelection(outermostNodes, null);
parentingSuccessful = true;
}

// check for nodes underneath the node we dropped
const parent: Node = eagle.logicalGraph().checkForNodeAt(outerMostNode.getPosition().x, outerMostNode.getPosition().y, outerMostNode.getRadius(), true);
// check for nodes underneath the node
const parent: Node = eagle.logicalGraph().checkForNodeAt(outermostNode.getPosition().x, outermostNode.getPosition().y, outermostNode.getRadius(), true);

// check if new candidate parent is already a descendent of the node, this would cause a circular hierarchy which would be bad
const ancestorOfParent = GraphRenderer.isAncestor(parent, outerMostNode);
// check if new candidate parent is already a descendent of the node, this would cause a circular hierarchy which would be bad
const ancestorOfParent = GraphRenderer.isAncestor(parent, outermostNode);

// if a parent was found, update
if (parent !== null && outerMostNode.getParentId() !== parent.getId() && outerMostNode.getId() !== parent.getId() && !ancestorOfParent && !outerMostNode.isEmbedded()){
GraphRenderer.updateNodeParent(outerMostNode, parent.getId(), allowGraphEditing);
GraphRenderer.NodeParentRadiusPreDrag = eagle.logicalGraph().findNodeByIdQuiet(parent.getId()).getRadius()
eagle.logicalGraph().fileInfo().modified = true;
}
if(!ancestorOfParent && parent != oldParent && parent != null){
// setting the new parent for all outermost selected nodes
GraphRenderer.parentSelection(outermostNodes, parent)
parentingSuccessful = true;
}

// if no parent found, update
if (parent === null && outerMostNode.getParentId() !== null && !outerMostNode.isEmbedded()){
GraphRenderer.updateNodeParent(outerMostNode, null, allowGraphEditing);
eagle.logicalGraph().fileInfo().modified = true;
if (parent === null && !outermostNode.isEmbedded() && oldParent !== null){
// moved out of a construct
$('#'+oldParent.getId()).addClass('transition')
GraphRenderer.parentSelection(outermostNodes, null);
parentingSuccessful = true;
}

if(parentingSuccessful){
eagle.logicalGraph().fileInfo().modified = true;
return
}
}
}

if (oldParent !== null){
// moved out of a construct
$('#'+oldParent.getId()).addClass('transition')
}
static parentSelection(outermostNodes : Node[], parent:Node) : void {

// recalculate size of parent (or oldParent)
if (parent === null){

} else {
// moved into or within a construct
$('#'+parent.getId()).removeClass('transition')
}
const allowGraphEditing = Setting.findValue(Setting.ALLOW_GRAPH_EDITING);
outermostNodes.forEach(function(object){
if(object instanceof Node){
if(!object.isEmbedded() && parent === null){
GraphRenderer.updateNodeParent(object, null, allowGraphEditing);
}else if(object.getId() != parent?.getId() && !object.isEmbedded()){
GraphRenderer.updateNodeParent(object, parent?.getId(), allowGraphEditing);
}
}
})

// resizing the parent construct to fit its new children
GraphRenderer.resizeConstruct(parent)

//updating the parent construct's "pre-drag" size at the end of parenting all the nodes
GraphRenderer.NodeParentRadiusPreDrag = Eagle.getInstance().logicalGraph().findNodeByIdQuiet(parent?.getId())?.getRadius()
}

static findNodesInRegion(left: number, right: number, top: number, bottom: number): Node[] {
Expand Down Expand Up @@ -1649,10 +1665,14 @@ export class GraphRenderer {
// resize a construct so that it contains its children
// NOTE: does not move the construct
static resizeConstruct = (construct: Node): void => {
if(construct === null){
return
}

const eagle = Eagle.getInstance();
let maxDistance = 0;

// loop through all children - find distance from center of construct
// loop through all nodes to fund children - then check to find distance from center of construct
for (const node of eagle.logicalGraph().getNodes()){
if(GraphRenderer.ctrlDrag && eagle.objectIsSelected(node) && !eagle.objectIsSelectedById(node.getParentId())){
continue
Expand Down

0 comments on commit ec33c39

Please sign in to comment.