Skip to content

Commit

Permalink
auto arrangement fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
sheikalthaf committed Oct 18, 2023
1 parent 5714e40 commit 99979f2
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 75 deletions.
12 changes: 5 additions & 7 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -514,14 +514,12 @@ export class FlowComponent
}

arrangeChildren() {
this.flow.connections = new Connections(this.list);
const arrangements = new Arrangements(
this.flow.connections,
this.getChildInfo()
);
console.log('new list', Object.fromEntries(arrangements.newList));
// this.flow.connections = new Connections(this.list);
const arrangements = new Arrangements(this.list);
const newList = arrangements.autoArrange();
console.log('new list', Object.fromEntries(newList));
this.flow.items.clear();
arrangements.newList.forEach((value, key) => {
newList.forEach((value, key) => {
this.flow.items.set(key, value);
});
this.flow.layoutUpdated.next();
Expand Down
80 changes: 25 additions & 55 deletions src/app/arrangements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,38 @@ import { FlowOptions } from './app.component';
import { ChildInfo, Connections } from './connections';

export class Arrangements {
newList = new Map<string, FlowOptions>();

direction: 'horizontal' | 'vertical' = 'horizontal';
horizontalPadding = 100;
verticalPadding = 100;
groupPadding = 0;
verticalPadding = 20;
groupPadding = 100;

constructor(
private connections: Connections,
private list: Record<string, ChildInfo>
) {
// console.count('Arrangements');
const values = structuredClone(Object.values(list).map((x) => x.position));
this.newList = this.autoArrange();
// console.log('list', values);
// console.log('newList values', structuredClone(Object.values(this.newList)));
}
constructor(private list: ChildInfo[]) {}

public autoArrange(): Map<string, FlowOptions> {
const levels = this.determineLevels();
const newItems = new Map<string, FlowOptions>();
let currentX = 0;

if (this.direction === 'horizontal') {
// Start by positioning the base nodes
const baseNodes = Object.values(this.list).filter(
const baseNodes = this.list.filter(
(node) => node.position.deps.length === 0
);

let level = 0;

for (const baseNode of baseNodes) {
const consumedHeight = this.positionDependents(
baseNode,
currentX - baseNode.elRect.width - this.horizontalPadding,
0,
newItems
);
const centerY = consumedHeight / 2;
newItems.set(baseNode.position.id, {
...baseNode.position,
x: currentX,
y: centerY - baseNode.elRect.height / 2,
});
// const centerY = consumedHeight / 2;
// newItems.set(baseNode.position.id, {
// ...baseNode.position,
// x: currentX,
// y: centerY - baseNode.elRect.height / 2,
// });
currentX +=
baseNode.elRect.width + this.horizontalPadding + this.groupPadding;
}
Expand Down Expand Up @@ -81,9 +71,10 @@ export class Arrangements {
baseNode: ChildInfo,
baseX: number,
baseY: number,
newItems: Map<string, FlowOptions>
): number {
const dependents = Object.values(this.list).filter((child) =>
newItems: Map<string, FlowOptions>,
isLast = false
): { consumedHeight: number } {
const dependents = this.list.filter((child) =>
child.position.deps.includes(baseNode.position.id)
);

Expand All @@ -95,15 +86,16 @@ export class Arrangements {
const height = baseNode.elRect.height;

for (let i = 0; i < dependents.length; i++) {
const depLast = i === dependents.length - 1;
const dependent = dependents[i];
const consumedHeight = this.positionDependents(
const { consumedHeight } = this.positionDependents(
dependent,
newX,
startY,
newItems
newItems,
depLast
);
startY =
consumedHeight + (i < dependents.length - 1 ? this.verticalPadding : 0);
startY = consumedHeight + (!depLast ? this.verticalPadding : 0);
}

const y =
Expand All @@ -114,32 +106,10 @@ export class Arrangements {
x: newX,
y: y,
});
return startY + (dependents.length ? 0 : height);
}

public determineLevels(): Map<string, number> {
const levels: Map<string, number> = new Map();
const processed: Set<string> = new Set();

const determineNodeLevel = (id: string, lvl: number) => {
if (!levels.has(id) || levels.get(id)! < lvl) {
levels.set(id, lvl);
}
processed.add(id);

const deps = this.connections.reverseDepsMap.get(id) || [];
deps.forEach((depId) => {
if (!processed.has(depId)) {
determineNodeLevel(depId, lvl + 1);
}
});
};

for (const [id, node] of Object.entries(this.list)) {
if (node.position.deps.length === 0) {
determineNodeLevel(id, 0);
}
if (!isLast && dependents.length > 1) {
startY += this.groupPadding;
}
return levels;
const consumedHeight = startY + (dependents.length ? 0 : height);
return { consumedHeight };
}
}
6 changes: 3 additions & 3 deletions src/app/connections.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('Connections', () => {
];

check(list, [1, 3]);
check(list.reverse(), [1, 3]);
check(list.reverse(), [3, 1]);

list = [
t({ x: 300, y: -150, id: '2', deps: ['1'] }),
Expand All @@ -27,7 +27,7 @@ describe('Connections', () => {
t({ x: 46, y: -470, id: '3', deps: ['2'] }),
t({ x: 300, y: -150, id: '2', deps: ['1'] }),
];
check(list, [3, 1]);
check(list, [1, 3]);

list = [
t({ x: 300, y: -150, id: '2', deps: ['1'] }),
Expand All @@ -52,7 +52,7 @@ describe('Connections', () => {
// connections = new Connections(list);
// let actual = connections.getClosestDotsSimplified(list[0], '2');
// expect(actual).toEqual([1, 3]);
check(list, 1, '1', [1, 3]);
check(list, 1, '1', [3, 1]);
// actual = connections.getClosestDotsSimplified(list[1], '1');
// expect(actual).toEqual([3, 1]);

Expand Down
5 changes: 3 additions & 2 deletions src/app/connections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,13 @@ export class Connections {
): [number, number] {
// sides dot index order: [top, right, bottom, left]
const thresholdDistance = 10; // Example distance threshold. Adjust as needed.

let swapped = false;
// correct the parent based on the deps
if (!child.position.deps.includes(parent.position.id)) {
const _t = child;
child = parent;
parent = _t;
swapped = true;
}

const childDirection: 'right' | 'left' | 'bottom' | 'top' = (() => {
Expand Down Expand Up @@ -116,7 +117,7 @@ export class Connections {
// [structuredClone(parent), structuredClone(child)]
// );

return [parentIndex, childIndex];
return swapped ? [childIndex, parentIndex] : [parentIndex, childIndex];
}

updateDotVisibility(childObj: Record<string, FlowChildComponent>) {
Expand Down
8 changes: 0 additions & 8 deletions src/app/flow.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,4 @@ describe('FlowComponent', () => {
'translate(0px, 0px) scale(1.01)'
);
});

it('should calc the path', () => {
const val = component.calculatePath(
{ x: 0, y: 0, id: '1', deps: [] },
{ x: 10, y: 10, id: '2', deps: [] }
);
expect(val).toEqual('M0 0 C5 1.1785113019775793 5 8.82148869802242 10 10');
});
});

0 comments on commit 99979f2

Please sign in to comment.