From 4e13a487e5b6dc60aab060d6cc369d0f793bfe3c Mon Sep 17 00:00:00 2001 From: Hanjx-bjtu <23281106@bjtu.edu.cn> Date: Fri, 21 Mar 2025 19:50:30 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=9F=BA?= =?UTF-8?q?=E4=BA=8Edagre-es=E6=B5=8B=E8=AF=95=E6=A0=B7=E4=BE=8B=E7=9A=84?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.component.ts | 255 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 src/app.component.ts diff --git a/src/app.component.ts b/src/app.component.ts new file mode 100644 index 0000000..466fd8e --- /dev/null +++ b/src/app.component.ts @@ -0,0 +1,255 @@ +// A test sample diagram based on darge-es. + +import { getLocaleNumberSymbol } from '@angular/common'; +import { asNativeElements, Component } from '@angular/core'; +import { RouterOutlet } from '@angular/router'; +import * as d3 from 'd3'; +import * as dagreD3 from 'dagre-d3-es'; +import { subscribeOn } from 'rxjs'; + +@Component({ + selector: 'app-root', + standalone: true, + imports: [RouterOutlet], + templateUrl: './app.component.html', + styleUrl: './app.component.css' +}) +export class AppComponent { + title = 'dagre-es-example'; + + ngOnInit() { + + // Create a new directed graph + var g = new dagreD3.graphlib.Graph({ directed: true }); + + // Set an object for the graph label + g.setGraph({}); + + g.graph().rankdir = "UD"; + g.graph().ranksep = 50; + g.graph().nodesep = 20; + + // Default to assigning a new object as a label for each new edge. + g.setDefaultEdgeLabel(function () { + return {}; + }); + + // const style = "stroke: black; fill: #eee; stroke-width: 1px; "; + + // Styles about nodes. + const dataNodeStyle = { + shape: "circle", + style: "stroke: blue; fill: orange; stroke-width: 1px;", + labelStyle: "font: 400 30px 'Arial', Arial; fill: white" + }; + + const actionNodeStyle = { + shape: "diamond", + style: "stroke: blue; fill: #32c8ff; stroke-width: 5px;", + labelstyle: "font: 400 30px 'Arial', Arial; fill: white" + }; + + const graphNodeStyle = { + shape: "circle", + style: "stroke: #32c8ff; fill: white; stroke-width: 10px;", + labelstyle: "font: 400 30px 'Arial', Arial; fill: white" + }; + + // Styles about dependences(edges). + const genDependStyle = { + curve: d3.curveMonotoneX, + style: "stroke: black; fill: none; stroke-width: 3px; stroke-dasharray: 5, 5;", + arrowheadStyle: "fill: grey" + }; + + const hyperDependStyle = { + curve: d3.curveBasis, + style: "stroke: blue; fill: none; stroke-width: 3px; stroke-dasharray: 5, 5;", + arrowheadStyle: "fill: gray" + }; + + const ctrlDependStyle = { + curve: d3.curveBasis, + style: "stroke: blue; fill: none; stroke-width: 1px; stroke-dasharray: 5, 5;", + arrowheadStyle: "fill: gray" + }; + + + // root + + // level 1 + g.setNode("w", { + label: "w", + width: 50, + height: 20, + ...dataNodeStyle + }); + g.setNode("x", { + label: "x", + width: 50, + height: 20, + ...dataNodeStyle + }); + g.setNode("sub1", { + label: "sub", + width: 50, + height: 20, + ...actionNodeStyle + }); + g.setNode("sub2", { + label: "sub", + width: 50, + height: 20, + ...actionNodeStyle + }); + + // level 2 + g.setNode("mul1", { + label: "mul", + width: 50, + height: 20, + ...actionNodeStyle + }); + g.setNode("b", { + label: "b", + width: 50, + height: 20, + ...dataNodeStyle + }); + g.setNode("mul2", { + label: "mul", + width: 50, + height: 20, + ...actionNodeStyle + }); + g.setNode("mul3", { + label: "mul", + width: 50, + height: 20, + ...actionNodeStyle + }); + g.setNode("eta", { + label: "η", + width: 50, + height: 20, + ...dataNodeStyle + }); + + // level 3 + g.setNode("add", { + label: "add", + width: 50, + height: 20, + ...actionNodeStyle + }); + g.setNode("y", { + label: "y", + width: 50, + height: 20, + ...dataNodeStyle + }); + g.setNode("mul4", { + label: "mul", + width: 50, + height: 20, + ...actionNodeStyle + }); + + + // level 4 + g.setNode("L", { + label: "L", + width: 50, + height: 20, + ...graphNodeStyle + }); + g.setNode("sub3", { + label: "sub", + width: 50, + height: 20, + ...actionNodeStyle + }); + + + // Add edges to the graph. + g.setEdge("x", "mul1", { + ...genDependStyle + }); + g.setEdge("x", "mul4", { + ...genDependStyle + }); + g.setEdge("w", "mul1", { + ...hyperDependStyle + }); + g.setEdge("w", "sub2", { + ...genDependStyle + }); + + g.setEdge("mul1", "add", { + ...genDependStyle + }); + + g.setEdge("b", "add", { + ...hyperDependStyle + }); + g.setEdge("b", "sub1", { + ...genDependStyle + }); + + g.setEdge("add", "L", { + ...genDependStyle + }); + g.setEdge("add", "sub3", { + ...genDependStyle + }); + + g.setEdge("y", "L", { + ...genDependStyle + }); + g.setEdge("y", "sub3", { + ...genDependStyle + }); + + g.setEdge("sub3", "mul2", { + ...genDependStyle + }); + g.setEdge("sub3", "mul4", { + ...genDependStyle + }); + + // g.setNode("mul4", "mul3", { + // ...genDependStyle + // }); + + g.setEdge("eta", "mul2", { + ...genDependStyle + }); + g.setEdge("eta", "mul3", { + ...genDependStyle + }); + + + var svg = d3.select("svg"), + inner = svg.select("g"); + + // // Create the renderer + var render = new (dagreD3 as any).render(); + + // // Run the renderer. This is what draws the final graph. + render(inner, g); + + inner + .selectAll("g.node") + .attr("title", function (v) { + return ( + "
" + + v + + "
some random description
" + ); + }) + .each(function (v) { + console.log("node details :", v); + // $(this).tipsy({ gravity: 'w', opacity: 1, html: true }); + }); + } +} From 755ed1faa4d7f51dae961dac4bfbca71f5665f5f Mon Sep 17 00:00:00 2001 From: Hanjx-bjtu <23281106@bjtu.edu.cn> Date: Sat, 12 Apr 2025 14:46:19 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=AE=80?= =?UTF-8?q?=E5=8D=95=E6=B5=8B=E8=AF=95=E6=A0=B7=E5=9B=BE=EF=BC=8C=E9=87=87?= =?UTF-8?q?=E7=94=A8=E7=AE=80=E6=98=93=E7=AE=97=E6=B3=95=E9=87=8D=E6=8E=92?= =?UTF-8?q?=E5=88=97=E8=8A=82=E7=82=B9=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.vue | 82 +++++++++++++- src/app.component.ts | 255 ------------------------------------------- src/designer.ts | 15 ++- src/objects/text.ts | 11 ++ 4 files changed, 101 insertions(+), 262 deletions(-) delete mode 100644 src/app.component.ts diff --git a/src/App.vue b/src/App.vue index 11bcefc..3228c6e 100644 --- a/src/App.vue +++ b/src/App.vue @@ -10,9 +10,13 @@ * * See the [Open Source License] for more details. * -* Author: Zhenjie Wei +* Oringial Author: Zhenjie Wei * Created: Jul. 20, 2023 * Supported by: National Key Research and Development Program of China +* +* Remake: Jiaxuan Han +* Date: Apr. 12, 2025 +* Tip: Add test graph by dividing nodes. --> @@ -32,6 +36,19 @@ import { uid_rt } from './logic/common/uid' const testStr = 'Once upon a time, 在远古村庄中, lived a clever little fox named Lily. Their friendship taught them that with kindness and determination, anything is possible. 故事完美落幕,他们的友谊将永远闪耀在心中。' +const dataNodeStyle = { + size: 20, + color: 'blue' +} +const actionNodeStyle = { + size: 20, + color: 'purple' +} +const subGraphNodeStyle = { + size: 30, + color: 'orange' +} + onMounted(() => { const scene = document.getElementById('scene') as HTMLCanvasElement @@ -103,11 +120,39 @@ onMounted(() => { 'sbend', ), ) - const t1 = new TextArea(Rect.fromLTWH(30, 20, 16, 8), testStr, { - size: 16, - color: 'red', - }) + var dn1 = new TextArea(Rect.fromLTWH(4, 4, 2, 2), "w", dataNodeStyle) + var dn2 = new TextArea(Rect.fromLTWH(8, 4, 2, 2), "x", dataNodeStyle) + var dn3 = new TextArea(Rect.fromLTWH(12, 4, 2, 2), "b", dataNodeStyle) + var dn4 = new TextArea(Rect.fromLTWH(16, 4, 2, 2), "y", dataNodeStyle) + var dn5 = new TextArea(Rect.fromLTWH(20, 4, 2, 2), "η", dataNodeStyle) + + var an_s1 = new TextArea(Rect.fromLTWH(4, 8, 3, 3), "sub", actionNodeStyle) + var an_s2 = new TextArea(Rect.fromLTWH(8, 8, 3, 3), "sub", actionNodeStyle) + var an_s3 = new TextArea(Rect.fromLTWH(12, 8, 3, 3), "sub", actionNodeStyle) + var an_a = new TextArea(Rect.fromLTWH(8, 12, 3, 3), "add", actionNodeStyle) + var an_m1 = new TextArea(Rect.fromLTWH(4, 16, 3, 3), "mul", actionNodeStyle) + var an_m2 = new TextArea(Rect.fromLTWH(8, 16, 3, 3), "mul", actionNodeStyle) + var an_m3 = new TextArea(Rect.fromLTWH(12, 16, 3, 3), "mul", actionNodeStyle) + var an_m4 = new TextArea(Rect.fromLTWH(16, 16, 3, 3), "mul", actionNodeStyle) + + + const t1 = new Component( + new RenderNode( + uid_rt(), + Rect.fromLTWH(30, 30, 4, 4), + [ + new RenderPort(2, PortType.IN, PortAspect.BOTTOM), + new RenderPort(2, PortType.OUT, PortAspect.RIGHT), + ], + '', + 'sbend', + ), + ) + + var sn1 = new TextArea(Rect.fromLTWH(10, 20, 4, 4), "L", subGraphNodeStyle) + + designer.addComponent(c1) designer.addComponent(c2) designer.addComponent(c3) @@ -116,10 +161,35 @@ onMounted(() => { designer.addComponent(c4) designer.addComponent(c5) + designer.addComponent(t1) core.switchMemory(core.createMemory()) - designer.addComponent(t1) + designer.addComponent(dn1) + designer.addComponent(dn2) + designer.addComponent(dn3) + designer.addComponent(dn4) + designer.addComponent(dn5) + + designer.addComponent(an_s1) + designer.addComponent(an_s2) + designer.addComponent(an_s3) + designer.addComponent(an_a) + designer.addComponent(an_m1) + designer.addComponent(an_m2) + designer.addComponent(an_m3) + designer.addComponent(an_m4) + + designer.addComponent(sn1) + + let layout = [ + [dn2, dn1, an_s1, an_s2], + [an_m1, dn3, an_m2, an_m3, dn5], + [an_a, dn4, an_m4], + [sn1, an_s3] + ] + + designer.reCalcLocate(layout) console.log(core) diff --git a/src/app.component.ts b/src/app.component.ts deleted file mode 100644 index 466fd8e..0000000 --- a/src/app.component.ts +++ /dev/null @@ -1,255 +0,0 @@ -// A test sample diagram based on darge-es. - -import { getLocaleNumberSymbol } from '@angular/common'; -import { asNativeElements, Component } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; -import * as d3 from 'd3'; -import * as dagreD3 from 'dagre-d3-es'; -import { subscribeOn } from 'rxjs'; - -@Component({ - selector: 'app-root', - standalone: true, - imports: [RouterOutlet], - templateUrl: './app.component.html', - styleUrl: './app.component.css' -}) -export class AppComponent { - title = 'dagre-es-example'; - - ngOnInit() { - - // Create a new directed graph - var g = new dagreD3.graphlib.Graph({ directed: true }); - - // Set an object for the graph label - g.setGraph({}); - - g.graph().rankdir = "UD"; - g.graph().ranksep = 50; - g.graph().nodesep = 20; - - // Default to assigning a new object as a label for each new edge. - g.setDefaultEdgeLabel(function () { - return {}; - }); - - // const style = "stroke: black; fill: #eee; stroke-width: 1px; "; - - // Styles about nodes. - const dataNodeStyle = { - shape: "circle", - style: "stroke: blue; fill: orange; stroke-width: 1px;", - labelStyle: "font: 400 30px 'Arial', Arial; fill: white" - }; - - const actionNodeStyle = { - shape: "diamond", - style: "stroke: blue; fill: #32c8ff; stroke-width: 5px;", - labelstyle: "font: 400 30px 'Arial', Arial; fill: white" - }; - - const graphNodeStyle = { - shape: "circle", - style: "stroke: #32c8ff; fill: white; stroke-width: 10px;", - labelstyle: "font: 400 30px 'Arial', Arial; fill: white" - }; - - // Styles about dependences(edges). - const genDependStyle = { - curve: d3.curveMonotoneX, - style: "stroke: black; fill: none; stroke-width: 3px; stroke-dasharray: 5, 5;", - arrowheadStyle: "fill: grey" - }; - - const hyperDependStyle = { - curve: d3.curveBasis, - style: "stroke: blue; fill: none; stroke-width: 3px; stroke-dasharray: 5, 5;", - arrowheadStyle: "fill: gray" - }; - - const ctrlDependStyle = { - curve: d3.curveBasis, - style: "stroke: blue; fill: none; stroke-width: 1px; stroke-dasharray: 5, 5;", - arrowheadStyle: "fill: gray" - }; - - - // root - - // level 1 - g.setNode("w", { - label: "w", - width: 50, - height: 20, - ...dataNodeStyle - }); - g.setNode("x", { - label: "x", - width: 50, - height: 20, - ...dataNodeStyle - }); - g.setNode("sub1", { - label: "sub", - width: 50, - height: 20, - ...actionNodeStyle - }); - g.setNode("sub2", { - label: "sub", - width: 50, - height: 20, - ...actionNodeStyle - }); - - // level 2 - g.setNode("mul1", { - label: "mul", - width: 50, - height: 20, - ...actionNodeStyle - }); - g.setNode("b", { - label: "b", - width: 50, - height: 20, - ...dataNodeStyle - }); - g.setNode("mul2", { - label: "mul", - width: 50, - height: 20, - ...actionNodeStyle - }); - g.setNode("mul3", { - label: "mul", - width: 50, - height: 20, - ...actionNodeStyle - }); - g.setNode("eta", { - label: "η", - width: 50, - height: 20, - ...dataNodeStyle - }); - - // level 3 - g.setNode("add", { - label: "add", - width: 50, - height: 20, - ...actionNodeStyle - }); - g.setNode("y", { - label: "y", - width: 50, - height: 20, - ...dataNodeStyle - }); - g.setNode("mul4", { - label: "mul", - width: 50, - height: 20, - ...actionNodeStyle - }); - - - // level 4 - g.setNode("L", { - label: "L", - width: 50, - height: 20, - ...graphNodeStyle - }); - g.setNode("sub3", { - label: "sub", - width: 50, - height: 20, - ...actionNodeStyle - }); - - - // Add edges to the graph. - g.setEdge("x", "mul1", { - ...genDependStyle - }); - g.setEdge("x", "mul4", { - ...genDependStyle - }); - g.setEdge("w", "mul1", { - ...hyperDependStyle - }); - g.setEdge("w", "sub2", { - ...genDependStyle - }); - - g.setEdge("mul1", "add", { - ...genDependStyle - }); - - g.setEdge("b", "add", { - ...hyperDependStyle - }); - g.setEdge("b", "sub1", { - ...genDependStyle - }); - - g.setEdge("add", "L", { - ...genDependStyle - }); - g.setEdge("add", "sub3", { - ...genDependStyle - }); - - g.setEdge("y", "L", { - ...genDependStyle - }); - g.setEdge("y", "sub3", { - ...genDependStyle - }); - - g.setEdge("sub3", "mul2", { - ...genDependStyle - }); - g.setEdge("sub3", "mul4", { - ...genDependStyle - }); - - // g.setNode("mul4", "mul3", { - // ...genDependStyle - // }); - - g.setEdge("eta", "mul2", { - ...genDependStyle - }); - g.setEdge("eta", "mul3", { - ...genDependStyle - }); - - - var svg = d3.select("svg"), - inner = svg.select("g"); - - // // Create the renderer - var render = new (dagreD3 as any).render(); - - // // Run the renderer. This is what draws the final graph. - render(inner, g); - - inner - .selectAll("g.node") - .attr("title", function (v) { - return ( - "" + - v + - "
some random description
" - ); - }) - .each(function (v) { - console.log("node details :", v); - // $(this).tipsy({ gravity: 'w', opacity: 1, html: true }); - }); - } -} diff --git a/src/designer.ts b/src/designer.ts index b02abd7..6d892e6 100644 --- a/src/designer.ts +++ b/src/designer.ts @@ -10,9 +10,12 @@ * * See the [Open Source License] for more details. * - * Author: Zhenjie Wei + * Original Author: Zhenjie Wei * Created: Oct. 24, 2023 * Supported by: National Key Research and Development Program of China + * + * Remake: Jiaxuan Han + * Date: Apr. 6, 2025 */ import LogicCore from './logic/core' @@ -30,6 +33,8 @@ import CompLayer from './layers/comp' import IRenderable from './logic/mixins/renderable' import { IObject } from './logic/handlers/object' import { graphManager } from './plugins/graph' +import { autoType } from 'd3' +import { Rect } from './logic/common/types2D' export default class Designer { private _core: LogicCore @@ -75,4 +80,12 @@ export default class Designer { this._core.register(comp) this._compLayer.addComponent(comp as unknown as IRenderable) } + + public reCalcLocate(layout: TextArea[][]){ + layout.forEach((row, j)=>{ + row.forEach((node, i) => { + node.recalcLoc(5 * i + 4, 5 * j + 4) + }); + }) + } } diff --git a/src/objects/text.ts b/src/objects/text.ts index 22b06df..1c1d473 100644 --- a/src/objects/text.ts +++ b/src/objects/text.ts @@ -13,6 +13,10 @@ * Author: Zhenjie Wei * Created: Sep. 15, 2023 * Supported by: National Key Research and Development Program of China + * + * Remake: Jiaxuan Han + * Date: Apr. 12, 2025 + * Tip: Add recalcLoc() to recalculate the location of TopLeft corner. */ import { Point, Rect } from '@/logic/common/types2D' @@ -28,6 +32,7 @@ export default class TextArea extends Flexible implements IRenderable, IDisposable { + [x: string]: any private _moving: boolean = false private _resizing: boolean = false private _arena: IObjectArena