From 17e4ae0e34ad981491614c09234e2e8c4b89f90e Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 21 Dec 2022 21:35:18 -0800 Subject: [PATCH 01/11] add shape_set_width_height test --- e2etests/todo_test.go | 118 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/e2etests/todo_test.go b/e2etests/todo_test.go index defa87cd6..925d791c8 100644 --- a/e2etests/todo_test.go +++ b/e2etests/todo_test.go @@ -90,6 +90,124 @@ this is a message group: { } }`, }, + { + // dimensions set on containers are ignored + name: "shape_set_width_height", + script: ` +containers: { + circle container: { + shape: circle + width: 512 + height: 256 + + diamond: { + shape: diamond + width: 128 + height: 64 + } + } + diamond container: { + shape: diamond + width: 512 + height: 256 + + circle: { + shape: circle + width: 128 + height: 64 + } + } + oval container: { + shape: oval + width: 512 + height: 256 + + hexagon: { + shape: hexagon + width: 128 + height: 64 + } + } + hexagon container: { + shape: hexagon + width: 512 + height: 256 + + oval: { + shape: oval + width: 128 + height: 64 + } + } +} + +cloud: { + shape: cloud + width: 512 + height: 256 +} +tall cylinder: { + shape: cylinder + width: 256 + height: 512 +} +cloud -> class -> tall cylinder -> users + +users: { + shape: sql_table + id: int + name: string + email: string + password: string + last_login: datetime + + width: 800 + height: 400 +} + +class: { + shape: class + -num: int + -timeout: int + -pid + + +getStatus(): Enum + +getJobs(): "Job[]" + +setTimeout(seconds int) + + width: 800 + height: 400 +} + +container -> text -> code -> small code + +text: { + label: |md + markdown text expanded to 800x400 +| + height: 800 + width: 400 +} + +code: |go + a := 5 + b := a + 7 + fmt.Printf("%d", b) +| { + width: 400 + height: 300 +} + +small code: |go + a := 5 + b := a + 7 + fmt.Printf("%d", b) +| { + width: 4 + height: 3 +} +`, + }, } runa(t, tcs) From 6cb72cb4175a4b5b46a82b68beafccf4fd2ea43b Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 28 Dec 2022 14:29:13 -0800 Subject: [PATCH 02/11] add unnamed_class_table_code regression test --- e2etests/regression_test.go | 33 ++ .../dagre/board.exp.json | 400 ++++++++++++++++++ .../dagre/sketch.exp.svg | 62 +++ .../elk/board.exp.json | 382 +++++++++++++++++ .../elk/sketch.exp.svg | 62 +++ 5 files changed, 939 insertions(+) create mode 100644 e2etests/testdata/regression/unnamed_class_table_code/dagre/board.exp.json create mode 100644 e2etests/testdata/regression/unnamed_class_table_code/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/regression/unnamed_class_table_code/elk/board.exp.json create mode 100644 e2etests/testdata/regression/unnamed_class_table_code/elk/sketch.exp.svg diff --git a/e2etests/regression_test.go b/e2etests/regression_test.go index d3fe777b6..f823b03c2 100644 --- a/e2etests/regression_test.go +++ b/e2etests/regression_test.go @@ -215,6 +215,39 @@ m6_desc: |md inserted here | m6_desc -> queue.M6 +`, + }, + { + name: "unnamed_class_table_code", + script: ` + +class -> users -> code + +class: "" { + shape: class + -num: int + -timeout: int + -pid + + +getStatus(): Enum + +getJobs(): "Job[]" + +setTimeout(seconds int) +} + +users: "" { + shape: sql_table + id: int + name: string + email: string + password: string + last_login: datetime +} + +code: |go + a := 5 + b := a + 7 + fmt.Printf("%d", b) +| `, }, } diff --git a/e2etests/testdata/regression/unnamed_class_table_code/dagre/board.exp.json b/e2etests/testdata/regression/unnamed_class_table_code/dagre/board.exp.json new file mode 100644 index 000000000..c01b08b63 --- /dev/null +++ b/e2etests/testdata/regression/unnamed_class_table_code/dagre/board.exp.json @@ -0,0 +1,400 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "class", + "type": "class", + "pos": { + "x": 48, + "y": 0 + }, + "width": 100, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": [ + { + "name": "num", + "type": "int", + "visibility": "private" + }, + { + "name": "timeout", + "type": "int", + "visibility": "private" + }, + { + "name": "pid", + "type": "", + "visibility": "private" + } + ], + "methods": [ + { + "name": "getStatus()", + "return": "Enum", + "visibility": "public" + }, + { + "name": "getJobs()", + "return": "Job[]", + "visibility": "public" + }, + { + "name": "setTimeout(seconds int)", + "return": "void", + "visibility": "public" + } + ], + "columns": null, + "label": "", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "users", + "type": "sql_table", + "pos": { + "x": 48, + "y": 200 + }, + "width": 100, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": [ + { + "name": { + "label": "id", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "type": { + "label": "int", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "name", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "email", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "password", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "last_login", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "type": { + "label": "datetime", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "constraint": "", + "reference": "" + } + ], + "label": "", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "code", + "type": "code", + "pos": { + "x": 0, + "y": 400 + }, + "width": 196, + "height": 70, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a := 5\nb := a + 7\nfmt.Printf(\"%d\", b)", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "golang", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 196, + "labelHeight": 70, + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(class -> users)[0]", + "src": "class", + "srcArrow": "none", + "srcLabel": "", + "dst": "users", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 98, + "y": 100 + }, + { + "x": 98, + "y": 140 + }, + { + "x": 98, + "y": 160 + }, + { + "x": 98, + "y": 200 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(users -> code)[0]", + "src": "users", + "srcArrow": "none", + "srcLabel": "", + "dst": "code", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 98, + "y": 300 + }, + { + "x": 98, + "y": 340 + }, + { + "x": 98, + "y": 360 + }, + { + "x": 98, + "y": 400 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/regression/unnamed_class_table_code/dagre/sketch.exp.svg b/e2etests/testdata/regression/unnamed_class_table_code/dagre/sketch.exp.svg new file mode 100644 index 000000000..323da486e --- /dev/null +++ b/e2etests/testdata/regression/unnamed_class_table_code/dagre/sketch.exp.svg @@ -0,0 +1,62 @@ + +- +num +int- +timeout +int- +pid ++ +getStatus() +Enum+ +getJobs() +Job[]+ +setTimeout(seconds int) +voidid +int +name +string +email +string +password +string +last_login +datetime +:= 5 +:= a + 7 +fmt.Printf("%d", b) + + + \ No newline at end of file diff --git a/e2etests/testdata/regression/unnamed_class_table_code/elk/board.exp.json b/e2etests/testdata/regression/unnamed_class_table_code/elk/board.exp.json new file mode 100644 index 000000000..f00297fb6 --- /dev/null +++ b/e2etests/testdata/regression/unnamed_class_table_code/elk/board.exp.json @@ -0,0 +1,382 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "class", + "type": "class", + "pos": { + "x": 60, + "y": 12 + }, + "width": 100, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": [ + { + "name": "num", + "type": "int", + "visibility": "private" + }, + { + "name": "timeout", + "type": "int", + "visibility": "private" + }, + { + "name": "pid", + "type": "", + "visibility": "private" + } + ], + "methods": [ + { + "name": "getStatus()", + "return": "Enum", + "visibility": "public" + }, + { + "name": "getJobs()", + "return": "Job[]", + "visibility": "public" + }, + { + "name": "setTimeout(seconds int)", + "return": "void", + "visibility": "public" + } + ], + "columns": null, + "label": "", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "users", + "type": "sql_table", + "pos": { + "x": 60, + "y": 212 + }, + "width": 100, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": [ + { + "name": { + "label": "id", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "type": { + "label": "int", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "name", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "email", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "password", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "last_login", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "type": { + "label": "datetime", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "constraint": "", + "reference": "" + } + ], + "label": "", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "code", + "type": "code", + "pos": { + "x": 12, + "y": 412 + }, + "width": 196, + "height": 70, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a := 5\nb := a + 7\nfmt.Printf(\"%d\", b)", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "golang", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 196, + "labelHeight": 70, + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(class -> users)[0]", + "src": "class", + "srcArrow": "none", + "srcLabel": "", + "dst": "users", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 110, + "y": 112 + }, + { + "x": 110, + "y": 212 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(users -> code)[0]", + "src": "users", + "srcArrow": "none", + "srcLabel": "", + "dst": "code", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 110, + "y": 312 + }, + { + "x": 110, + "y": 412 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/regression/unnamed_class_table_code/elk/sketch.exp.svg b/e2etests/testdata/regression/unnamed_class_table_code/elk/sketch.exp.svg new file mode 100644 index 000000000..944f77f35 --- /dev/null +++ b/e2etests/testdata/regression/unnamed_class_table_code/elk/sketch.exp.svg @@ -0,0 +1,62 @@ + +- +num +int- +timeout +int- +pid ++ +getStatus() +Enum+ +getJobs() +Job[]+ +setTimeout(seconds int) +voidid +int +name +string +email +string +password +string +last_login +datetime +:= 5 +:= a + 7 +fmt.Printf("%d", b) + + + \ No newline at end of file From 5d4059e470692cfd6a4b46d508639f3f68fbab1b Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 21 Dec 2022 21:36:08 -0800 Subject: [PATCH 03/11] support setting width/height on non-image shapes --- d2compiler/compile.go | 7 - d2compiler/compile_test.go | 3 - d2graph/d2graph.go | 101 +- .../dagre/board.exp.json | 98 +- .../dagre/sketch.exp.svg | 52 +- .../elk/board.exp.json | 82 +- .../elk/sketch.exp.svg | 52 +- .../dagre/board.exp.json | 1175 +++++++++++++++++ .../dagre/sketch.exp.svg | 71 + .../shape_set_width_height/elk/board.exp.json | 1097 +++++++++++++++ .../shape_set_width_height/elk/sketch.exp.svg | 71 + .../dimensions_on_nonimage.exp.json | 214 ++- 12 files changed, 2837 insertions(+), 186 deletions(-) create mode 100644 e2etests/testdata/todo/shape_set_width_height/dagre/board.exp.json create mode 100644 e2etests/testdata/todo/shape_set_width_height/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/todo/shape_set_width_height/elk/board.exp.json create mode 100644 e2etests/testdata/todo/shape_set_width_height/elk/sketch.exp.svg diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 86e6e63d3..5429bdea4 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -801,13 +801,6 @@ func (c *compiler) validateKey(obj *d2graph.Object, m *d2ast.Map, mk *d2ast.Key) c.errorf(mk.Range.Start, mk.Range.End, "image shapes cannot have children.") } - if reserved == "width" && obj.Attributes.Shape.Value != d2target.ShapeImage { - c.errorf(mk.Range.Start, mk.Range.End, "width is only applicable to image shapes.") - } - if reserved == "height" && obj.Attributes.Shape.Value != d2target.ShapeImage { - c.errorf(mk.Range.Start, mk.Range.End, "height is only applicable to image shapes.") - } - in := d2target.IsShape(obj.Attributes.Shape.Value) _, arrowheadIn := d2target.Arrowheads[obj.Attributes.Shape.Value] if !in && arrowheadIn { diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index cf7283649..207211e1d 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -94,9 +94,6 @@ x: { width: 200 height: 230 } -`, - expErr: `d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2:3:2: width is only applicable to image shapes. -d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2:4:2: height is only applicable to image shapes. `, }, { diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index 6ab44e7f1..53f682942 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -898,17 +898,36 @@ func appendTextDedup(texts []*d2target.MText, t *d2target.MText) []*d2target.MTe func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler, fontFamily *d2fonts.FontFamily) error { for _, obj := range g.Objects { obj.Box = &geo.Box{} - // TODO fix edge cases for unnamed class etc - // Image shapes can set their own widths/heights - if obj.Attributes.Label.Value == "" && obj.Attributes.Shape.Value != d2target.ShapeImage { - obj.Width = 100 - obj.Height = 100 - continue + + var setWidth int + var setHeight int + if obj.Attributes.Width != nil { + setWidth, _ = strconv.Atoi(obj.Attributes.Width.Value) + } + if obj.Attributes.Height != nil { + setHeight, _ = strconv.Atoi(obj.Attributes.Height.Value) + } + shapeType := strings.ToLower(obj.Attributes.Shape.Value) + + switch shapeType { + case d2target.ShapeClass, + d2target.ShapeSQLTable, + d2target.ShapeCode, + d2target.ShapeImage, + d2target.ShapeText: + // edge cases for unnamed class, etc + default: + if obj.Attributes.Label.Value == "" && setWidth == 0 && setHeight == 0 { + obj.Width = 100 + obj.Height = 100 + continue + } } var dims *d2target.TextDimensions var innerLabelPadding = INNER_LABEL_PADDING - if obj.Attributes.Shape.Value == d2target.ShapeText { + switch shapeType { + case d2target.ShapeText: if obj.Attributes.Language == "latex" { width, height, err := d2latex.Measure(obj.Text().Text) if err != nil { @@ -925,20 +944,30 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler dims = GetTextDimensions(mtexts, ruler, obj.Text(), fontFamily) } innerLabelPadding = 0 - } else if obj.Attributes.Shape.Value == d2target.ShapeClass { + + case d2target.ShapeClass: dims = GetTextDimensions(mtexts, ruler, obj.Text(), go2.Pointer(d2fonts.SourceCodePro)) - } else { + + default: dims = GetTextDimensions(mtexts, ruler, obj.Text(), fontFamily) } + + if shapeType == d2target.ShapeSQLTable && obj.Attributes.Label.Value == "" { + // measure with placeholder text to determine height + placeholder := *obj.Text() + placeholder.Text = "Table" + dims = GetTextDimensions(mtexts, ruler, &placeholder, fontFamily) + } + if dims == nil { - if obj.Attributes.Shape.Value == d2target.ShapeImage { + if shapeType == d2target.ShapeImage { dims = d2target.NewTextDimensions(0, 0) } else { return fmt.Errorf("dimensions for object label %#v not found", obj.Text()) } } - switch obj.Attributes.Shape.Value { + switch shapeType { case d2target.ShapeText, d2target.ShapeClass, d2target.ShapeSQLTable, d2target.ShapeCode: // no labels default: @@ -954,29 +983,39 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler obj.Width = float64(dims.Width) obj.Height = float64(dims.Height) - switch strings.ToLower(obj.Attributes.Shape.Value) { + // the set dimensions must be at least as large as the text + if float64(setWidth) > obj.Width { + obj.Width = float64(setWidth) + } + if float64(setHeight) > obj.Height { + obj.Height = float64(setHeight) + } + + switch shapeType { default: - obj.Width += 100 - obj.Height += 100 + if setWidth == 0 { + obj.Width += 100 + } + if setHeight == 0 { + obj.Height += 100 + } case d2target.ShapeImage: - if obj.Attributes.Width != nil { - w, _ := strconv.Atoi(obj.Attributes.Width.Value) - obj.Width = float64(w) - } else { + if setWidth == 0 { obj.Width = 128 } - if obj.Attributes.Height != nil { - h, _ := strconv.Atoi(obj.Attributes.Height.Value) - obj.Height = float64(h) - } else { + if setHeight == 0 { obj.Height = 128 } case d2target.ShapeSquare, d2target.ShapeCircle: sideLength := go2.Max(obj.Width, obj.Height) - obj.Width = sideLength + 100 - obj.Height = sideLength + 100 + padding := 0. + if setWidth == 0 && setHeight == 0 { + padding = 100. + } + obj.Width = sideLength + padding + obj.Height = sideLength + padding case d2target.ShapeClass: maxWidth := dims.Width @@ -1059,6 +1098,20 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler case d2target.ShapeText, d2target.ShapeCode: } + + switch shapeType { + case d2target.ShapeClass, + d2target.ShapeSQLTable, + d2target.ShapeCode, + d2target.ShapeText: + if float64(setWidth) > obj.Width { + obj.Width = float64(setWidth) + } + if float64(setHeight) > obj.Height { + obj.Height = float64(setHeight) + } + } + } for _, edge := range g.Edges { endpointLabels := []string{} diff --git a/e2etests/testdata/regression/unnamed_class_table_code/dagre/board.exp.json b/e2etests/testdata/regression/unnamed_class_table_code/dagre/board.exp.json index c01b08b63..f96e89a36 100644 --- a/e2etests/testdata/regression/unnamed_class_table_code/dagre/board.exp.json +++ b/e2etests/testdata/regression/unnamed_class_table_code/dagre/board.exp.json @@ -6,11 +6,11 @@ "id": "class", "type": "class", "pos": { - "x": 48, + "x": 0, "y": 0 }, - "width": 100, - "height": 100, + "width": 422, + "height": 368, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -68,8 +68,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 0, - "labelHeight": 0, + "labelWidth": 5, + "labelHeight": 5, "zIndex": 0, "level": 1, "primaryAccentColor": "#0D32B2", @@ -80,11 +80,11 @@ "id": "users", "type": "sql_table", "pos": { - "x": 48, - "y": 200 + "x": 107, + "y": 468 }, - "width": 100, - "height": 100, + "width": 208, + "height": 216, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -112,8 +112,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 0, - "labelHeight": 0 + "labelWidth": 15, + "labelHeight": 26 }, "type": { "label": "int", @@ -124,8 +124,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 0, - "labelHeight": 0 + "labelWidth": 23, + "labelHeight": 26 }, "constraint": "", "reference": "" @@ -140,8 +140,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 0, - "labelHeight": 0 + "labelWidth": 47, + "labelHeight": 26 }, "type": { "label": "string", @@ -152,8 +152,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 0, - "labelHeight": 0 + "labelWidth": 48, + "labelHeight": 26 }, "constraint": "", "reference": "" @@ -168,8 +168,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 0, - "labelHeight": 0 + "labelWidth": 47, + "labelHeight": 26 }, "type": { "label": "string", @@ -180,8 +180,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 0, - "labelHeight": 0 + "labelWidth": 48, + "labelHeight": 26 }, "constraint": "", "reference": "" @@ -196,8 +196,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 0, - "labelHeight": 0 + "labelWidth": 80, + "labelHeight": 26 }, "type": { "label": "string", @@ -208,8 +208,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 0, - "labelHeight": 0 + "labelWidth": 48, + "labelHeight": 26 }, "constraint": "", "reference": "" @@ -224,8 +224,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 0, - "labelHeight": 0 + "labelWidth": 81, + "labelHeight": 26 }, "type": { "label": "datetime", @@ -236,8 +236,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 0, - "labelHeight": 0 + "labelWidth": 77, + "labelHeight": 26 }, "constraint": "", "reference": "" @@ -251,8 +251,8 @@ "italic": false, "bold": true, "underline": false, - "labelWidth": 0, - "labelHeight": 0, + "labelWidth": 64, + "labelHeight": 36, "zIndex": 0, "level": 1, "primaryAccentColor": "#0D32B2", @@ -263,8 +263,8 @@ "id": "code", "type": "code", "pos": { - "x": 0, - "y": 400 + "x": 113, + "y": 784 }, "width": 196, "height": 70, @@ -326,20 +326,20 @@ "labelPercentage": 0, "route": [ { - "x": 98, - "y": 100 + "x": 211, + "y": 368 }, { - "x": 98, - "y": 140 + "x": 211, + "y": 408 }, { - "x": 98, - "y": 160 + "x": 211, + "y": 428 }, { - "x": 98, - "y": 200 + "x": 211, + "y": 468 } ], "isCurve": true, @@ -374,20 +374,20 @@ "labelPercentage": 0, "route": [ { - "x": 98, - "y": 300 + "x": 211, + "y": 684 }, { - "x": 98, - "y": 340 + "x": 211, + "y": 724 }, { - "x": 98, - "y": 360 + "x": 211, + "y": 744 }, { - "x": 98, - "y": 400 + "x": 211, + "y": 784 } ], "isCurve": true, diff --git a/e2etests/testdata/regression/unnamed_class_table_code/dagre/sketch.exp.svg b/e2etests/testdata/regression/unnamed_class_table_code/dagre/sketch.exp.svg index 323da486e..15c3051ff 100644 --- a/e2etests/testdata/regression/unnamed_class_table_code/dagre/sketch.exp.svg +++ b/e2etests/testdata/regression/unnamed_class_table_code/dagre/sketch.exp.svg @@ -2,7 +2,7 @@ - +num +int- +timeout +int- +pid ++ +getStatus() +Enum+ +getJobs() +Job[]+ +setTimeout(seconds int) +voidid +int +name +string +email +string +password +string +last_login +datetime +:= 5 := a + 7 -fmt.Printf("%d", b) - +fmt.Printf("%d", b) + - -num -int- -timeout -int- -pid -+ -getStatus() -Enum+ -getJobs() -Job[]+ -setTimeout(seconds int) -voidid -int -name -string -email -string -password -string -last_login -datetime -:= 5 +- +num +int- +timeout +int- +pid ++ +getStatus() +Enum+ +getJobs() +Job[]+ +setTimeout(seconds int) +voidid +int +name +string +email +string +password +string +last_login +datetime +:= 5 := a + 7 -fmt.Printf("%d", b) - +fmt.Printf("%d", b) + containerscloudtall cylinderusersid +int +name +string +email +string +password +string +last_login +datetime +class- +num +int- +timeout +int- +pid ++ +getStatus() +Enum+ +getJobs() +Job[]+ +setTimeout(seconds int) +voidmarkdown text expanded to 800x400:= 5 +:= a + 7 +fmt.Printf("%d", b):= 5 +:= a + 7 +fmt.Printf("%d", b)containercircle containerdiamond containeroval containerhexagon containerdiamondcirclehexagonoval + + + \ No newline at end of file diff --git a/e2etests/testdata/todo/shape_set_width_height/elk/board.exp.json b/e2etests/testdata/todo/shape_set_width_height/elk/board.exp.json new file mode 100644 index 000000000..61577b1dd --- /dev/null +++ b/e2etests/testdata/todo/shape_set_width_height/elk/board.exp.json @@ -0,0 +1,1097 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "containers", + "type": "", + "pos": { + "x": 12, + "y": 12 + }, + "width": 1322, + "height": 428, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#E3E9FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "containers", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 128, + "labelHeight": 41, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "containers.circle container", + "type": "oval", + "pos": { + "x": 87, + "y": 119 + }, + "width": 278, + "height": 214, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "circle container", + "fontSize": 24, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 161, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "containers.circle container.diamond", + "type": "diamond", + "pos": { + "x": 162, + "y": 194 + }, + "width": 128, + "height": 64, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#CFD2DD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "diamond", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 68, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 3 + }, + { + "id": "containers.diamond container", + "type": "diamond", + "pos": { + "x": 385, + "y": 87 + }, + "width": 278, + "height": 278, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#CFD2DD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "diamond container", + "fontSize": 24, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 197, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "containers.diamond container.circle", + "type": "oval", + "pos": { + "x": 460, + "y": 162 + }, + "width": 128, + "height": 128, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "circle", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 44, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 3 + }, + { + "id": "containers.oval container", + "type": "oval", + "pos": { + "x": 683, + "y": 119 + }, + "width": 278, + "height": 214, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "oval container", + "fontSize": 24, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 149, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "containers.oval container.hexagon", + "type": "hexagon", + "pos": { + "x": 758, + "y": 194 + }, + "width": 128, + "height": 64, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#DEE1EB", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "hexagon", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 65, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 3 + }, + { + "id": "containers.hexagon container", + "type": "hexagon", + "pos": { + "x": 981, + "y": 119 + }, + "width": 278, + "height": 214, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#DEE1EB", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "hexagon container", + "fontSize": 24, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 193, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "containers.hexagon container.oval", + "type": "oval", + "pos": { + "x": 1056, + "y": 194 + }, + "width": 128, + "height": 64, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "oval", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 36, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 3 + }, + { + "id": "cloud", + "type": "cloud", + "pos": { + "x": 1354, + "y": 184 + }, + "width": 512, + "height": 256, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "cloud", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 45, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "tall cylinder", + "type": "cylinder", + "pos": { + "x": 1482, + "y": 1440 + }, + "width": 256, + "height": 512, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "tall cylinder", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 91, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "users", + "type": "sql_table", + "pos": { + "x": 1210, + "y": 2052 + }, + "width": 800, + "height": 400, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": [ + { + "name": { + "label": "id", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 15, + "labelHeight": 26 + }, + "type": { + "label": "int", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 23, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "name", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 47, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "email", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 47, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "password", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 80, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "last_login", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 81, + "labelHeight": 26 + }, + "type": { + "label": "datetime", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 77, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + } + ], + "label": "users", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 61, + "labelHeight": 36, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "class", + "type": "class", + "pos": { + "x": 1210, + "y": 740 + }, + "width": 800, + "height": 400, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": [ + { + "name": "num", + "type": "int", + "visibility": "private" + }, + { + "name": "timeout", + "type": "int", + "visibility": "private" + }, + { + "name": "pid", + "type": "", + "visibility": "private" + } + ], + "methods": [ + { + "name": "getStatus()", + "return": "Enum", + "visibility": "public" + }, + { + "name": "getJobs()", + "return": "Job[]", + "visibility": "public" + }, + { + "name": "setTimeout(seconds int)", + "return": "void", + "visibility": "public" + } + ], + "columns": null, + "label": "class", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 75, + "labelHeight": 36, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "text", + "type": "", + "pos": { + "x": 2030, + "y": 540 + }, + "width": 400, + "height": 800, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "markdown text expanded to 800x400", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 266, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "code", + "type": "code", + "pos": { + "x": 2030, + "y": 1546 + }, + "width": 400, + "height": 300, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a := 5\nb := a + 7\nfmt.Printf(\"%d\", b)", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "golang", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 196, + "labelHeight": 70, + "zIndex": 0, + "level": 1 + }, + { + "id": "small code", + "type": "code", + "pos": { + "x": 2132, + "y": 2052 + }, + "width": 196, + "height": 70, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a := 5\nb := a + 7\nfmt.Printf(\"%d\", b)", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "golang", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 196, + "labelHeight": 70, + "zIndex": 0, + "level": 1 + }, + { + "id": "container", + "type": "", + "pos": { + "x": 2143, + "y": 314 + }, + "width": 174, + "height": 126, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "container", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 74, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(cloud -> class)[0]", + "src": "cloud", + "srcArrow": "none", + "srcLabel": "", + "dst": "class", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1610, + "y": 440 + }, + { + "x": 1610, + "y": 740 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(class -> tall cylinder)[0]", + "src": "class", + "srcArrow": "none", + "srcLabel": "", + "dst": "tall cylinder", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1610, + "y": 1140 + }, + { + "x": 1610, + "y": 1440 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(tall cylinder -> users)[0]", + "src": "tall cylinder", + "srcArrow": "none", + "srcLabel": "", + "dst": "users", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1610, + "y": 1952 + }, + { + "x": 1610, + "y": 2052 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(container -> text)[0]", + "src": "container", + "srcArrow": "none", + "srcLabel": "", + "dst": "text", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 2230, + "y": 440 + }, + { + "x": 2230, + "y": 540 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(text -> code)[0]", + "src": "text", + "srcArrow": "none", + "srcLabel": "", + "dst": "code", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 2230, + "y": 1340 + }, + { + "x": 2230, + "y": 1546 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(code -> small code)[0]", + "src": "code", + "srcArrow": "none", + "srcLabel": "", + "dst": "small code", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 2230, + "y": 1846 + }, + { + "x": 2230, + "y": 2052 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/todo/shape_set_width_height/elk/sketch.exp.svg b/e2etests/testdata/todo/shape_set_width_height/elk/sketch.exp.svg new file mode 100644 index 000000000..509a9bf1e --- /dev/null +++ b/e2etests/testdata/todo/shape_set_width_height/elk/sketch.exp.svg @@ -0,0 +1,71 @@ + +containerscloudtall cylinderusersid +int +name +string +email +string +password +string +last_login +datetime +class- +num +int- +timeout +int- +pid ++ +getStatus() +Enum+ +getJobs() +Job[]+ +setTimeout(seconds int) +voidmarkdown text expanded to 800x400:= 5 +:= a + 7 +fmt.Printf("%d", b):= 5 +:= a + 7 +fmt.Printf("%d", b)containercircle containerdiamond containeroval containerhexagon containerdiamondcirclehexagonoval + + + \ No newline at end of file diff --git a/testdata/d2compiler/TestCompile/dimensions_on_nonimage.exp.json b/testdata/d2compiler/TestCompile/dimensions_on_nonimage.exp.json index 405923ccf..d094c9039 100644 --- a/testdata/d2compiler/TestCompile/dimensions_on_nonimage.exp.json +++ b/testdata/d2compiler/TestCompile/dimensions_on_nonimage.exp.json @@ -1,16 +1,210 @@ { - "graph": null, - "err": { - "ioerr": null, - "errs": [ - { - "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,2:1:28-2:11:38", - "errmsg": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2:3:2: width is only applicable to image shapes." + "graph": { + "ast": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,0:0:0-5:0:54", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,0:0:0-4:1:53", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,0:0:0-0:3:3", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,0:0:0-0:3:3", + "value": [ + { + "string": "hey", + "raw_string": "hey" + } + ] + } + } + ] + }, + "primary": { + "double_quoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,0:5:5-0:7:7", + "value": null + } + }, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,0:8:8-4:0:52", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,1:2:12-1:16:26", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,1:2:12-1:7:17", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,1:2:12-1:7:17", + "value": [ + { + "string": "shape", + "raw_string": "shape" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,1:9:19-1:16:26", + "value": [ + { + "string": "hexagon", + "raw_string": "hexagon" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,2:1:28-2:11:38", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,2:1:28-2:6:33", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,2:1:28-2:6:33", + "value": [ + { + "string": "width", + "raw_string": "width" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "number": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,2:8:35-2:11:38", + "raw": "200", + "value": "200" + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,3:1:40-3:12:51", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,3:1:40-3:7:46", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,3:1:40-3:7:46", + "value": [ + { + "string": "height", + "raw_string": "height" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "number": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,3:9:48-3:12:51", + "raw": "230", + "value": "230" + } + } + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "label_dimensions": { + "width": 0, + "height": 0 }, + "attributes": { + "label": { + "value": "" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + } + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ { - "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,3:1:40-3:12:51", - "errmsg": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2:4:2: height is only applicable to image shapes." + "id": "hey", + "id_val": "hey", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,0:0:0-0:3:3", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/dimensions_on_nonimage.d2,0:0:0-0:3:3", + "value": [ + { + "string": "hey", + "raw_string": "hey" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "" + }, + "style": {}, + "width": { + "value": "200" + }, + "height": { + "value": "230" + }, + "near_key": null, + "shape": { + "value": "hexagon" + }, + "direction": { + "value": "" + } + }, + "zIndex": 0 } ] - } + }, + "err": null } From e45f78b50cb4dcb349bb610b37272adeccb2c601 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 21 Dec 2022 21:36:32 -0800 Subject: [PATCH 04/11] changelog --- ci/release/changelogs/next.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 1078069ca..54e278b56 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -5,6 +5,9 @@ #### Improvements 🧹 +- Now the `width` and `height` attributes are no longer restricted to images and can be applied to non-container shapes. [#498](https://github.com/terrastruct/d2/pull/498) + #### Bugfixes ⛑️ - Restricts where `near` key constant values can be used, with good error messages, instead of erroring (e.g. setting `near: top-center` on a container would cause bad layouts or error). [#538](https://github.com/terrastruct/d2/pull/538) +- Fixed rendering classes and tables with empty headers. [#498](https://github.com/terrastruct/d2/pull/498) From 73d1a666e18c347e2cc931871c1b0717dc245ed7 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 28 Dec 2022 15:58:00 -0800 Subject: [PATCH 05/11] cleanup --- ci/release/changelogs/next.md | 5 ++--- d2graph/d2graph.go | 41 +++++++++++++++-------------------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 54e278b56..4457be55c 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -2,12 +2,11 @@ - Tooltips can be set on shapes. See [https://d2lang.com/tour/tooltips](https://d2lang.com/tour/interactive). [#548](https://github.com/terrastruct/d2/pull/548) - Links can be set on shapes. See [https://d2lang.com/tour/tooltips](https://d2lang.com/tour/interactive). [#548](https://github.com/terrastruct/d2/pull/548) +- The `width` and `height` attributes are no longer restricted to images and can be applied to non-container shapes. [#498](https://github.com/terrastruct/d2/pull/498) #### Improvements 🧹 -- Now the `width` and `height` attributes are no longer restricted to images and can be applied to non-container shapes. [#498](https://github.com/terrastruct/d2/pull/498) - #### Bugfixes ⛑️ - Restricts where `near` key constant values can be used, with good error messages, instead of erroring (e.g. setting `near: top-center` on a container would cause bad layouts or error). [#538](https://github.com/terrastruct/d2/pull/538) -- Fixed rendering classes and tables with empty headers. [#498](https://github.com/terrastruct/d2/pull/498) +- Fixes rendering classes and tables with empty headers. [#498](https://github.com/terrastruct/d2/pull/498) diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index 53f682942..1b667c665 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -899,13 +899,13 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler for _, obj := range g.Objects { obj.Box = &geo.Box{} - var setWidth int - var setHeight int + var desiredWidth int + var desiredHeight int if obj.Attributes.Width != nil { - setWidth, _ = strconv.Atoi(obj.Attributes.Width.Value) + desiredWidth, _ = strconv.Atoi(obj.Attributes.Width.Value) } if obj.Attributes.Height != nil { - setHeight, _ = strconv.Atoi(obj.Attributes.Height.Value) + desiredHeight, _ = strconv.Atoi(obj.Attributes.Height.Value) } shapeType := strings.ToLower(obj.Attributes.Shape.Value) @@ -917,7 +917,7 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler d2target.ShapeText: // edge cases for unnamed class, etc default: - if obj.Attributes.Label.Value == "" && setWidth == 0 && setHeight == 0 { + if obj.Attributes.Label.Value == "" && desiredWidth == 0 && desiredHeight == 0 { obj.Width = 100 obj.Height = 100 continue @@ -980,38 +980,31 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler dims.Width += innerLabelPadding dims.Height += innerLabelPadding obj.LabelDimensions = *dims - obj.Width = float64(dims.Width) - obj.Height = float64(dims.Height) - - // the set dimensions must be at least as large as the text - if float64(setWidth) > obj.Width { - obj.Width = float64(setWidth) - } - if float64(setHeight) > obj.Height { - obj.Height = float64(setHeight) - } + // the desired dimensions must be at least as large as the text + obj.Width = float64(go2.Max(dims.Width, desiredWidth)) + obj.Height = float64(go2.Max(dims.Height, desiredHeight)) switch shapeType { default: - if setWidth == 0 { + if desiredWidth == 0 { obj.Width += 100 } - if setHeight == 0 { + if desiredHeight == 0 { obj.Height += 100 } case d2target.ShapeImage: - if setWidth == 0 { + if desiredWidth == 0 { obj.Width = 128 } - if setHeight == 0 { + if desiredHeight == 0 { obj.Height = 128 } case d2target.ShapeSquare, d2target.ShapeCircle: sideLength := go2.Max(obj.Width, obj.Height) padding := 0. - if setWidth == 0 && setHeight == 0 { + if desiredWidth == 0 && desiredHeight == 0 { padding = 100. } obj.Width = sideLength + padding @@ -1104,11 +1097,11 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler d2target.ShapeSQLTable, d2target.ShapeCode, d2target.ShapeText: - if float64(setWidth) > obj.Width { - obj.Width = float64(setWidth) + if float64(desiredWidth) > obj.Width { + obj.Width = float64(desiredWidth) } - if float64(setHeight) > obj.Height { - obj.Height = float64(setHeight) + if float64(desiredHeight) > obj.Height { + obj.Height = float64(desiredHeight) } } From 2f4446ee1895b3f7a8a8ed4b7a6f41d28c5b34fb Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 28 Dec 2022 16:05:56 -0800 Subject: [PATCH 06/11] add tests with only width or height set --- e2etests/stable_test.go | 84 +++ .../unnamed_only_height/dagre/board.exp.json | 574 ++++++++++++++++++ .../unnamed_only_height/dagre/sketch.exp.svg | 62 ++ .../unnamed_only_height/elk/board.exp.json | 538 ++++++++++++++++ .../unnamed_only_height/elk/sketch.exp.svg | 62 ++ .../unnamed_only_width/dagre/board.exp.json | 574 ++++++++++++++++++ .../unnamed_only_width/dagre/sketch.exp.svg | 62 ++ .../unnamed_only_width/elk/board.exp.json | 538 ++++++++++++++++ .../unnamed_only_width/elk/sketch.exp.svg | 62 ++ 9 files changed, 2556 insertions(+) create mode 100644 e2etests/testdata/stable/unnamed_only_height/dagre/board.exp.json create mode 100644 e2etests/testdata/stable/unnamed_only_height/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/stable/unnamed_only_height/elk/board.exp.json create mode 100644 e2etests/testdata/stable/unnamed_only_height/elk/sketch.exp.svg create mode 100644 e2etests/testdata/stable/unnamed_only_width/dagre/board.exp.json create mode 100644 e2etests/testdata/stable/unnamed_only_width/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/stable/unnamed_only_width/elk/board.exp.json create mode 100644 e2etests/testdata/stable/unnamed_only_width/elk/sketch.exp.svg diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go index e43d84921..6590d295e 100644 --- a/e2etests/stable_test.go +++ b/e2etests/stable_test.go @@ -1638,6 +1638,90 @@ x -> y script: `x: { link: https://d2lang.com } y: { link: https://terrastruct.com; tooltip: Gee, I feel kind of LIGHT in the head now,\nknowing I can't make my satellite dish PAYMENTS! } x -> y +`, + }, + { + name: "unnamed_only_width", + script: ` + +class -> users -> code -> package -> no width + +class: "" { + shape: class + -num: int + -timeout: int + -pid + + +getStatus(): Enum + +getJobs(): "Job[]" + +setTimeout(seconds int) +} + +users: "" { + shape: sql_table + id: int + name: string + email: string + password: string + last_login: datetime +} + +code: |go + a := 5 + b := a + 7 + fmt.Printf("%d", b) +| + +package: "" { shape: package } +no width: "" + + +class.width: 512 +users.width: 512 +code.width: 512 +package.width: 512 +`, + }, + { + name: "unnamed_only_height", + script: ` + +class -> users -> code -> package -> no height + +class: "" { + shape: class + -num: int + -timeout: int + -pid + + +getStatus(): Enum + +getJobs(): "Job[]" + +setTimeout(seconds int) +} + +users: "" { + shape: sql_table + id: int + name: string + email: string + password: string + last_login: datetime +} + +code: |go + a := 5 + b := a + 7 + fmt.Printf("%d", b) +| + +package: "" { shape: package } +no height: "" + + +class.height: 512 +users.height: 512 +code.height: 512 +package.height: 512 `, }, } diff --git a/e2etests/testdata/stable/unnamed_only_height/dagre/board.exp.json b/e2etests/testdata/stable/unnamed_only_height/dagre/board.exp.json new file mode 100644 index 000000000..e54467ba5 --- /dev/null +++ b/e2etests/testdata/stable/unnamed_only_height/dagre/board.exp.json @@ -0,0 +1,574 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "class", + "type": "class", + "pos": { + "x": 0, + "y": 0 + }, + "width": 422, + "height": 512, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": [ + { + "name": "num", + "type": "int", + "visibility": "private" + }, + { + "name": "timeout", + "type": "int", + "visibility": "private" + }, + { + "name": "pid", + "type": "", + "visibility": "private" + } + ], + "methods": [ + { + "name": "getStatus()", + "return": "Enum", + "visibility": "public" + }, + { + "name": "getJobs()", + "return": "Job[]", + "visibility": "public" + }, + { + "name": "setTimeout(seconds int)", + "return": "void", + "visibility": "public" + } + ], + "columns": null, + "label": "", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 5, + "labelHeight": 5, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "users", + "type": "sql_table", + "pos": { + "x": 107, + "y": 612 + }, + "width": 208, + "height": 512, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": [ + { + "name": { + "label": "id", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 15, + "labelHeight": 26 + }, + "type": { + "label": "int", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 23, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "name", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 47, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "email", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 47, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "password", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 80, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "last_login", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 81, + "labelHeight": 26 + }, + "type": { + "label": "datetime", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 77, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + } + ], + "label": "", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 64, + "labelHeight": 36, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "code", + "type": "code", + "pos": { + "x": 113, + "y": 1224 + }, + "width": 196, + "height": 512, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a := 5\nb := a + 7\nfmt.Printf(\"%d\", b)", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "golang", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 196, + "labelHeight": 70, + "zIndex": 0, + "level": 1 + }, + { + "id": "package", + "type": "package", + "pos": { + "x": 159, + "y": 1836 + }, + "width": 105, + "height": 512, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 5, + "labelHeight": 5, + "zIndex": 0, + "level": 1 + }, + { + "id": "no height", + "type": "", + "pos": { + "x": 161, + "y": 2448 + }, + "width": 100, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(class -> users)[0]", + "src": "class", + "srcArrow": "none", + "srcLabel": "", + "dst": "users", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 211, + "y": 512 + }, + { + "x": 211, + "y": 552 + }, + { + "x": 211, + "y": 572 + }, + { + "x": 211, + "y": 612 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(users -> code)[0]", + "src": "users", + "srcArrow": "none", + "srcLabel": "", + "dst": "code", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 211, + "y": 1124 + }, + { + "x": 211, + "y": 1164 + }, + { + "x": 211, + "y": 1184 + }, + { + "x": 211, + "y": 1224 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(code -> package)[0]", + "src": "code", + "srcArrow": "none", + "srcLabel": "", + "dst": "package", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 211, + "y": 1736 + }, + { + "x": 211, + "y": 1776 + }, + { + "x": 211, + "y": 1796 + }, + { + "x": 211, + "y": 1836 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(package -> no height)[0]", + "src": "package", + "srcArrow": "none", + "srcLabel": "", + "dst": "no height", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 211, + "y": 2348 + }, + { + "x": 211, + "y": 2388 + }, + { + "x": 211, + "y": 2408 + }, + { + "x": 211, + "y": 2448 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/stable/unnamed_only_height/dagre/sketch.exp.svg b/e2etests/testdata/stable/unnamed_only_height/dagre/sketch.exp.svg new file mode 100644 index 000000000..0c882d8ca --- /dev/null +++ b/e2etests/testdata/stable/unnamed_only_height/dagre/sketch.exp.svg @@ -0,0 +1,62 @@ + +- +num +int- +timeout +int- +pid ++ +getStatus() +Enum+ +getJobs() +Job[]+ +setTimeout(seconds int) +voidid +int +name +string +email +string +password +string +last_login +datetime +:= 5 +:= a + 7 +fmt.Printf("%d", b) + + + \ No newline at end of file diff --git a/e2etests/testdata/stable/unnamed_only_height/elk/board.exp.json b/e2etests/testdata/stable/unnamed_only_height/elk/board.exp.json new file mode 100644 index 000000000..86a3b84d8 --- /dev/null +++ b/e2etests/testdata/stable/unnamed_only_height/elk/board.exp.json @@ -0,0 +1,538 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "class", + "type": "class", + "pos": { + "x": 12, + "y": 12 + }, + "width": 422, + "height": 512, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": [ + { + "name": "num", + "type": "int", + "visibility": "private" + }, + { + "name": "timeout", + "type": "int", + "visibility": "private" + }, + { + "name": "pid", + "type": "", + "visibility": "private" + } + ], + "methods": [ + { + "name": "getStatus()", + "return": "Enum", + "visibility": "public" + }, + { + "name": "getJobs()", + "return": "Job[]", + "visibility": "public" + }, + { + "name": "setTimeout(seconds int)", + "return": "void", + "visibility": "public" + } + ], + "columns": null, + "label": "", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 5, + "labelHeight": 5, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "users", + "type": "sql_table", + "pos": { + "x": 119, + "y": 624 + }, + "width": 208, + "height": 512, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": [ + { + "name": { + "label": "id", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 15, + "labelHeight": 26 + }, + "type": { + "label": "int", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 23, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "name", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 47, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "email", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 47, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "password", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 80, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "last_login", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 81, + "labelHeight": 26 + }, + "type": { + "label": "datetime", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 77, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + } + ], + "label": "", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 64, + "labelHeight": 36, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "code", + "type": "code", + "pos": { + "x": 125, + "y": 1236 + }, + "width": 196, + "height": 512, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a := 5\nb := a + 7\nfmt.Printf(\"%d\", b)", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "golang", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 196, + "labelHeight": 70, + "zIndex": 0, + "level": 1 + }, + { + "id": "package", + "type": "package", + "pos": { + "x": 170, + "y": 1848 + }, + "width": 105, + "height": 512, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 5, + "labelHeight": 5, + "zIndex": 0, + "level": 1 + }, + { + "id": "no height", + "type": "", + "pos": { + "x": 173, + "y": 2460 + }, + "width": 100, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(class -> users)[0]", + "src": "class", + "srcArrow": "none", + "srcLabel": "", + "dst": "users", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 223, + "y": 524 + }, + { + "x": 223, + "y": 624 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(users -> code)[0]", + "src": "users", + "srcArrow": "none", + "srcLabel": "", + "dst": "code", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 223, + "y": 1136 + }, + { + "x": 223, + "y": 1236 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(code -> package)[0]", + "src": "code", + "srcArrow": "none", + "srcLabel": "", + "dst": "package", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 223, + "y": 1748 + }, + { + "x": 224, + "y": 1848 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(package -> no height)[0]", + "src": "package", + "srcArrow": "none", + "srcLabel": "", + "dst": "no height", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 223, + "y": 2360 + }, + { + "x": 223, + "y": 2460 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/stable/unnamed_only_height/elk/sketch.exp.svg b/e2etests/testdata/stable/unnamed_only_height/elk/sketch.exp.svg new file mode 100644 index 000000000..490221200 --- /dev/null +++ b/e2etests/testdata/stable/unnamed_only_height/elk/sketch.exp.svg @@ -0,0 +1,62 @@ + +- +num +int- +timeout +int- +pid ++ +getStatus() +Enum+ +getJobs() +Job[]+ +setTimeout(seconds int) +voidid +int +name +string +email +string +password +string +last_login +datetime +:= 5 +:= a + 7 +fmt.Printf("%d", b) + + + \ No newline at end of file diff --git a/e2etests/testdata/stable/unnamed_only_width/dagre/board.exp.json b/e2etests/testdata/stable/unnamed_only_width/dagre/board.exp.json new file mode 100644 index 000000000..15add77d7 --- /dev/null +++ b/e2etests/testdata/stable/unnamed_only_width/dagre/board.exp.json @@ -0,0 +1,574 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "class", + "type": "class", + "pos": { + "x": 0, + "y": 0 + }, + "width": 512, + "height": 368, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": [ + { + "name": "num", + "type": "int", + "visibility": "private" + }, + { + "name": "timeout", + "type": "int", + "visibility": "private" + }, + { + "name": "pid", + "type": "", + "visibility": "private" + } + ], + "methods": [ + { + "name": "getStatus()", + "return": "Enum", + "visibility": "public" + }, + { + "name": "getJobs()", + "return": "Job[]", + "visibility": "public" + }, + { + "name": "setTimeout(seconds int)", + "return": "void", + "visibility": "public" + } + ], + "columns": null, + "label": "", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 5, + "labelHeight": 5, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "users", + "type": "sql_table", + "pos": { + "x": 0, + "y": 468 + }, + "width": 512, + "height": 216, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": [ + { + "name": { + "label": "id", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 15, + "labelHeight": 26 + }, + "type": { + "label": "int", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 23, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "name", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 47, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "email", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 47, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "password", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 80, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "last_login", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 81, + "labelHeight": 26 + }, + "type": { + "label": "datetime", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 77, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + } + ], + "label": "", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 64, + "labelHeight": 36, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "code", + "type": "code", + "pos": { + "x": 0, + "y": 784 + }, + "width": 512, + "height": 70, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a := 5\nb := a + 7\nfmt.Printf(\"%d\", b)", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "golang", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 196, + "labelHeight": 70, + "zIndex": 0, + "level": 1 + }, + { + "id": "package", + "type": "package", + "pos": { + "x": 0, + "y": 954 + }, + "width": 512, + "height": 105, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 5, + "labelHeight": 5, + "zIndex": 0, + "level": 1 + }, + { + "id": "no width", + "type": "", + "pos": { + "x": 206, + "y": 1159 + }, + "width": 100, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(class -> users)[0]", + "src": "class", + "srcArrow": "none", + "srcLabel": "", + "dst": "users", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 256, + "y": 368 + }, + { + "x": 256, + "y": 408 + }, + { + "x": 256, + "y": 428 + }, + { + "x": 256, + "y": 468 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(users -> code)[0]", + "src": "users", + "srcArrow": "none", + "srcLabel": "", + "dst": "code", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 256, + "y": 684 + }, + { + "x": 256, + "y": 724 + }, + { + "x": 256, + "y": 744 + }, + { + "x": 256, + "y": 784 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(code -> package)[0]", + "src": "code", + "srcArrow": "none", + "srcLabel": "", + "dst": "package", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 256, + "y": 854 + }, + { + "x": 256, + "y": 894 + }, + { + "x": 256, + "y": 920.8 + }, + { + "x": 256, + "y": 988 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(package -> no width)[0]", + "src": "package", + "srcArrow": "none", + "srcLabel": "", + "dst": "no width", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 256, + "y": 1059 + }, + { + "x": 256, + "y": 1099 + }, + { + "x": 256, + "y": 1119 + }, + { + "x": 256, + "y": 1159 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/stable/unnamed_only_width/dagre/sketch.exp.svg b/e2etests/testdata/stable/unnamed_only_width/dagre/sketch.exp.svg new file mode 100644 index 000000000..96703e437 --- /dev/null +++ b/e2etests/testdata/stable/unnamed_only_width/dagre/sketch.exp.svg @@ -0,0 +1,62 @@ + +- +num +int- +timeout +int- +pid ++ +getStatus() +Enum+ +getJobs() +Job[]+ +setTimeout(seconds int) +voidid +int +name +string +email +string +password +string +last_login +datetime +:= 5 +:= a + 7 +fmt.Printf("%d", b) + + + \ No newline at end of file diff --git a/e2etests/testdata/stable/unnamed_only_width/elk/board.exp.json b/e2etests/testdata/stable/unnamed_only_width/elk/board.exp.json new file mode 100644 index 000000000..feb0395df --- /dev/null +++ b/e2etests/testdata/stable/unnamed_only_width/elk/board.exp.json @@ -0,0 +1,538 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "class", + "type": "class", + "pos": { + "x": 12, + "y": 12 + }, + "width": 512, + "height": 368, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": [ + { + "name": "num", + "type": "int", + "visibility": "private" + }, + { + "name": "timeout", + "type": "int", + "visibility": "private" + }, + { + "name": "pid", + "type": "", + "visibility": "private" + } + ], + "methods": [ + { + "name": "getStatus()", + "return": "Enum", + "visibility": "public" + }, + { + "name": "getJobs()", + "return": "Job[]", + "visibility": "public" + }, + { + "name": "setTimeout(seconds int)", + "return": "void", + "visibility": "public" + } + ], + "columns": null, + "label": "", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 5, + "labelHeight": 5, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "users", + "type": "sql_table", + "pos": { + "x": 12, + "y": 480 + }, + "width": 512, + "height": 216, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#0A0F25", + "stroke": "#FFFFFF", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": [ + { + "name": { + "label": "id", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 15, + "labelHeight": 26 + }, + "type": { + "label": "int", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 23, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "name", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 47, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "email", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 47, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "password", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 80, + "labelHeight": 26 + }, + "type": { + "label": "string", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 48, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + }, + { + "name": { + "label": "last_login", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 81, + "labelHeight": 26 + }, + "type": { + "label": "datetime", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 77, + "labelHeight": 26 + }, + "constraint": "", + "reference": "" + } + ], + "label": "", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 64, + "labelHeight": 36, + "zIndex": 0, + "level": 1, + "primaryAccentColor": "#0D32B2", + "secondaryAccentColor": "#4A6FF3", + "neutralAccentColor": "#676C7E" + }, + { + "id": "code", + "type": "code", + "pos": { + "x": 12, + "y": 796 + }, + "width": 512, + "height": 70, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "a := 5\nb := a + 7\nfmt.Printf(\"%d\", b)", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "golang", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 196, + "labelHeight": 70, + "zIndex": 0, + "level": 1 + }, + { + "id": "package", + "type": "package", + "pos": { + "x": 12, + "y": 966 + }, + "width": 512, + "height": 105, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#EDF0FD", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 5, + "labelHeight": 5, + "zIndex": 0, + "level": 1 + }, + { + "id": "no width", + "type": "", + "pos": { + "x": 218, + "y": 1171 + }, + "width": 100, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(class -> users)[0]", + "src": "class", + "srcArrow": "none", + "srcLabel": "", + "dst": "users", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 268, + "y": 380 + }, + { + "x": 268, + "y": 480 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(users -> code)[0]", + "src": "users", + "srcArrow": "none", + "srcLabel": "", + "dst": "code", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 268, + "y": 696 + }, + { + "x": 268, + "y": 796 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(code -> package)[0]", + "src": "code", + "srcArrow": "none", + "srcLabel": "", + "dst": "package", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 268, + "y": 866 + }, + { + "x": 268, + "y": 1000 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(package -> no width)[0]", + "src": "package", + "srcArrow": "none", + "srcLabel": "", + "dst": "no width", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 268, + "y": 1071 + }, + { + "x": 268, + "y": 1171 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/stable/unnamed_only_width/elk/sketch.exp.svg b/e2etests/testdata/stable/unnamed_only_width/elk/sketch.exp.svg new file mode 100644 index 000000000..5e434c0cb --- /dev/null +++ b/e2etests/testdata/stable/unnamed_only_width/elk/sketch.exp.svg @@ -0,0 +1,62 @@ + +- +num +int- +timeout +int- +pid ++ +getStatus() +Enum+ +getJobs() +Job[]+ +setTimeout(seconds int) +voidid +int +name +string +email +string +password +string +last_login +datetime +:= 5 +:= a + 7 +fmt.Printf("%d", b) + + + \ No newline at end of file From 8384d96763743dd604c3177a5e8887c193497cb9 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 28 Dec 2022 18:14:19 -0800 Subject: [PATCH 07/11] refactor SetDimensions --- d2graph/d2graph.go | 383 ++++++++++++++++++++++++--------------------- 1 file changed, 206 insertions(+), 177 deletions(-) diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index 1b667c665..60af1b33d 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -3,6 +3,7 @@ package d2graph import ( "errors" "fmt" + "math" "net/url" "strconv" "strings" @@ -21,6 +22,7 @@ import ( ) const INNER_LABEL_PADDING int = 5 +const DEFAULT_SHAPE_PADDING = 100. // TODO: Refactor with a light abstract layer on top of AST implementing scenarios, // variables, imports, substitutions and then a final set of structures representing @@ -668,6 +670,164 @@ func (obj *Object) AppendReferences(ida []string, ref Reference, unresolvedObj * } } +func (obj *Object) GetLabelSize(mtexts []*d2target.MText, ruler *textmeasure.Ruler, fontFamily *d2fonts.FontFamily) (*d2target.TextDimensions, error) { + shapeType := strings.ToLower(obj.Attributes.Shape.Value) + + var dims *d2target.TextDimensions + switch shapeType { + case d2target.ShapeText: + if obj.Attributes.Language == "latex" { + width, height, err := d2latex.Measure(obj.Text().Text) + if err != nil { + return nil, err + } + dims = d2target.NewTextDimensions(width, height) + } else if obj.Attributes.Language != "" { + var err error + dims, err = getMarkdownDimensions(mtexts, ruler, obj.Text(), fontFamily) + if err != nil { + return nil, err + } + } else { + dims = GetTextDimensions(mtexts, ruler, obj.Text(), fontFamily) + } + + case d2target.ShapeClass: + dims = GetTextDimensions(mtexts, ruler, obj.Text(), go2.Pointer(d2fonts.SourceCodePro)) + + default: + dims = GetTextDimensions(mtexts, ruler, obj.Text(), fontFamily) + } + + if shapeType == d2target.ShapeSQLTable && obj.Attributes.Label.Value == "" { + // measure with placeholder text to determine height + placeholder := *obj.Text() + placeholder.Text = "Table" + dims = GetTextDimensions(mtexts, ruler, &placeholder, fontFamily) + } + + if dims == nil { + if shapeType == d2target.ShapeImage { + dims = d2target.NewTextDimensions(0, 0) + } else { + return nil, fmt.Errorf("dimensions for object label %#v not found", obj.Text()) + } + } + + return dims, nil +} + +func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.Ruler, fontFamily *d2fonts.FontFamily, labelDims d2target.TextDimensions) (*d2target.TextDimensions, error) { + dims := d2target.TextDimensions{} + + shapeType := strings.ToLower(obj.Attributes.Shape.Value) + + switch shapeType { + default: + return d2target.NewTextDimensions(labelDims.Width, labelDims.Height), nil + + case d2target.ShapeImage: + return d2target.NewTextDimensions(128, 128), nil + + case d2target.ShapeClass: + maxWidth := labelDims.Width + + for _, f := range obj.Class.Fields { + fdims := GetTextDimensions(mtexts, ruler, f.Text(), go2.Pointer(d2fonts.SourceCodePro)) + if fdims == nil { + return nil, fmt.Errorf("dimensions for class field %#v not found", f.Text()) + } + lineWidth := fdims.Width + if maxWidth < lineWidth { + maxWidth = lineWidth + } + } + for _, m := range obj.Class.Methods { + mdims := GetTextDimensions(mtexts, ruler, m.Text(), go2.Pointer(d2fonts.SourceCodePro)) + if mdims == nil { + return nil, fmt.Errorf("dimensions for class method %#v not found", m.Text()) + } + lineWidth := mdims.Width + if maxWidth < lineWidth { + maxWidth = lineWidth + } + } + dims.Width = maxWidth + + // All rows should be the same height + var anyRowText *d2target.MText + if len(obj.Class.Fields) > 0 { + anyRowText = obj.Class.Fields[0].Text() + } else if len(obj.Class.Methods) > 0 { + anyRowText = obj.Class.Methods[0].Text() + } + if anyRowText != nil { + // 10px of padding top and bottom so text doesn't look squished + rowHeight := GetTextDimensions(mtexts, ruler, anyRowText, go2.Pointer(d2fonts.SourceCodePro)).Height + 20 + dims.Height = rowHeight * (len(obj.Class.Fields) + len(obj.Class.Methods) + 2) + } else { + dims.Height = labelDims.Height + } + + case d2target.ShapeSQLTable: + maxNameWidth := 0 + maxTypeWidth := 0 + constraintWidth := 0 + + for i := range obj.SQLTable.Columns { + // Note: we want to set dimensions of actual column not the for loop copy of the struct + c := &obj.SQLTable.Columns[i] + ctexts := c.Texts() + + nameDims := GetTextDimensions(mtexts, ruler, ctexts[0], fontFamily) + if nameDims == nil { + return nil, fmt.Errorf("dimensions for sql_table name %#v not found", ctexts[0].Text) + } + c.Name.LabelWidth = nameDims.Width + c.Name.LabelHeight = nameDims.Height + if maxNameWidth < nameDims.Width { + maxNameWidth = nameDims.Width + } + + typeDims := GetTextDimensions(mtexts, ruler, ctexts[1], fontFamily) + if typeDims == nil { + return nil, fmt.Errorf("dimensions for sql_table type %#v not found", ctexts[1].Text) + } + c.Type.LabelWidth = typeDims.Width + c.Type.LabelHeight = typeDims.Height + if maxTypeWidth < typeDims.Width { + maxTypeWidth = typeDims.Width + } + + if c.Constraint != "" { + // covers UNQ constraint with padding + constraintWidth = 60 + } + } + + // The rows get padded a little due to header font being larger than row font + dims.Height = labelDims.Height * (len(obj.SQLTable.Columns) + 1) + dims.Width = d2target.NamePadding + maxNameWidth + d2target.TypePadding + maxTypeWidth + d2target.TypePadding + constraintWidth + } + return &dims, nil +} + +func (obj *Object) GetPadding() (x, y float64) { + + switch strings.ToLower(obj.Attributes.Shape.Value) { + case d2target.ShapeImage, + d2target.ShapeSQLTable, + d2target.ShapeText, + d2target.ShapeCode: + return 0., 0. + case d2target.ShapeClass: + // TODO fix class row width measurements (see SQL table) + return 100., 0. + default: + return DEFAULT_SHAPE_PADDING, DEFAULT_SHAPE_PADDING + } +} + type Edge struct { Index int `json:"index"` @@ -909,62 +1069,24 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler } shapeType := strings.ToLower(obj.Attributes.Shape.Value) - switch shapeType { - case d2target.ShapeClass, - d2target.ShapeSQLTable, - d2target.ShapeCode, - d2target.ShapeImage, - d2target.ShapeText: - // edge cases for unnamed class, etc - default: - if obj.Attributes.Label.Value == "" && desiredWidth == 0 && desiredHeight == 0 { - obj.Width = 100 - obj.Height = 100 - continue - } - } + // switch shapeType { + // case d2target.ShapeClass, + // d2target.ShapeSQLTable, + // d2target.ShapeCode, + // d2target.ShapeImage, + // d2target.ShapeText: + // // edge cases for unnamed class, etc + // default: + // if obj.Attributes.Label.Value == "" && desiredWidth == 0 && desiredHeight == 0 { + // obj.Width = 100 + // obj.Height = 100 + // continue + // } + // } - var dims *d2target.TextDimensions - var innerLabelPadding = INNER_LABEL_PADDING - switch shapeType { - case d2target.ShapeText: - if obj.Attributes.Language == "latex" { - width, height, err := d2latex.Measure(obj.Text().Text) - if err != nil { - return err - } - dims = d2target.NewTextDimensions(width, height) - } else if obj.Attributes.Language != "" { - var err error - dims, err = getMarkdownDimensions(mtexts, ruler, obj.Text(), fontFamily) - if err != nil { - return err - } - } else { - dims = GetTextDimensions(mtexts, ruler, obj.Text(), fontFamily) - } - innerLabelPadding = 0 - - case d2target.ShapeClass: - dims = GetTextDimensions(mtexts, ruler, obj.Text(), go2.Pointer(d2fonts.SourceCodePro)) - - default: - dims = GetTextDimensions(mtexts, ruler, obj.Text(), fontFamily) - } - - if shapeType == d2target.ShapeSQLTable && obj.Attributes.Label.Value == "" { - // measure with placeholder text to determine height - placeholder := *obj.Text() - placeholder.Text = "Table" - dims = GetTextDimensions(mtexts, ruler, &placeholder, fontFamily) - } - - if dims == nil { - if shapeType == d2target.ShapeImage { - dims = d2target.NewTextDimensions(0, 0) - } else { - return fmt.Errorf("dimensions for object label %#v not found", obj.Text()) - } + labelDims, err := obj.GetLabelSize(mtexts, ruler, fontFamily) + if err != nil { + return err } switch shapeType { @@ -972,139 +1094,46 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler // no labels default: if obj.Attributes.Label.Value != "" { - obj.LabelWidth = go2.Pointer(dims.Width) - obj.LabelHeight = go2.Pointer(dims.Height) + obj.LabelWidth = go2.Pointer(labelDims.Width) + obj.LabelHeight = go2.Pointer(labelDims.Height) } } - dims.Width += innerLabelPadding - dims.Height += innerLabelPadding - obj.LabelDimensions = *dims - // the desired dimensions must be at least as large as the text - obj.Width = float64(go2.Max(dims.Width, desiredWidth)) - obj.Height = float64(go2.Max(dims.Height, desiredHeight)) + if shapeType != d2target.ShapeText && obj.Attributes.Label.Value != "" { + labelDims.Width += INNER_LABEL_PADDING + labelDims.Height += INNER_LABEL_PADDING + } + obj.LabelDimensions = *labelDims + + defaultDims, err := obj.GetDefaultSize(mtexts, ruler, fontFamily, *labelDims) + if err != nil { + return err + } + + obj.Width = float64(go2.Max(defaultDims.Width, desiredWidth)) + obj.Height = float64(go2.Max(defaultDims.Height, desiredHeight)) + + paddingX, paddingY := obj.GetPadding() switch shapeType { + case d2target.ShapeSquare, d2target.ShapeCircle: + if desiredWidth != 0 || desiredHeight != 0 { + paddingX = 0. + paddingY = 0. + } + + sideLength := math.Max(obj.Width+paddingX, obj.Height+paddingY) + obj.Width = sideLength + obj.Height = sideLength + default: if desiredWidth == 0 { - obj.Width += 100 + obj.Width += float64(paddingX) } if desiredHeight == 0 { - obj.Height += 100 - } - - case d2target.ShapeImage: - if desiredWidth == 0 { - obj.Width = 128 - } - if desiredHeight == 0 { - obj.Height = 128 - } - - case d2target.ShapeSquare, d2target.ShapeCircle: - sideLength := go2.Max(obj.Width, obj.Height) - padding := 0. - if desiredWidth == 0 && desiredHeight == 0 { - padding = 100. - } - obj.Width = sideLength + padding - obj.Height = sideLength + padding - - case d2target.ShapeClass: - maxWidth := dims.Width - - for _, f := range obj.Class.Fields { - fdims := GetTextDimensions(mtexts, ruler, f.Text(), go2.Pointer(d2fonts.SourceCodePro)) - if fdims == nil { - return fmt.Errorf("dimensions for class field %#v not found", f.Text()) - } - lineWidth := fdims.Width - if maxWidth < lineWidth { - maxWidth = lineWidth - } - } - for _, m := range obj.Class.Methods { - mdims := GetTextDimensions(mtexts, ruler, m.Text(), go2.Pointer(d2fonts.SourceCodePro)) - if mdims == nil { - return fmt.Errorf("dimensions for class method %#v not found", m.Text()) - } - lineWidth := mdims.Width - if maxWidth < lineWidth { - maxWidth = lineWidth - } - } - - // All rows should be the same height - var anyRowText *d2target.MText - if len(obj.Class.Fields) > 0 { - anyRowText = obj.Class.Fields[0].Text() - } else if len(obj.Class.Methods) > 0 { - anyRowText = obj.Class.Methods[0].Text() - } - if anyRowText != nil { - // 10px of padding top and bottom so text doesn't look squished - rowHeight := GetTextDimensions(mtexts, ruler, anyRowText, go2.Pointer(d2fonts.SourceCodePro)).Height + 20 - obj.Height = float64(rowHeight * (len(obj.Class.Fields) + len(obj.Class.Methods) + 2)) - } - // Leave room for padding - obj.Width = float64(maxWidth + 100) - - case d2target.ShapeSQLTable: - maxNameWidth := 0 - maxTypeWidth := 0 - constraintWidth := 0 - - for i := range obj.SQLTable.Columns { - // Note: we want to set dimensions of actual column not the for loop copy of the struct - c := &obj.SQLTable.Columns[i] - ctexts := c.Texts() - - nameDims := GetTextDimensions(mtexts, ruler, ctexts[0], fontFamily) - if nameDims == nil { - return fmt.Errorf("dimensions for sql_table name %#v not found", ctexts[0].Text) - } - c.Name.LabelWidth = nameDims.Width - c.Name.LabelHeight = nameDims.Height - if maxNameWidth < nameDims.Width { - maxNameWidth = nameDims.Width - } - - typeDims := GetTextDimensions(mtexts, ruler, ctexts[1], fontFamily) - if typeDims == nil { - return fmt.Errorf("dimensions for sql_table type %#v not found", ctexts[1].Text) - } - c.Type.LabelWidth = typeDims.Width - c.Type.LabelHeight = typeDims.Height - if maxTypeWidth < typeDims.Width { - maxTypeWidth = typeDims.Width - } - - if c.Constraint != "" { - // covers UNQ constraint with padding - constraintWidth = 60 - } - } - - // The rows get padded a little due to header font being larger than row font - obj.Height = float64(dims.Height * (len(obj.SQLTable.Columns) + 1)) - obj.Width = float64(d2target.NamePadding + maxNameWidth + d2target.TypePadding + maxTypeWidth + d2target.TypePadding + constraintWidth) - - case d2target.ShapeText, d2target.ShapeCode: - } - - switch shapeType { - case d2target.ShapeClass, - d2target.ShapeSQLTable, - d2target.ShapeCode, - d2target.ShapeText: - if float64(desiredWidth) > obj.Width { - obj.Width = float64(desiredWidth) - } - if float64(desiredHeight) > obj.Height { - obj.Height = float64(desiredHeight) + obj.Height += float64(paddingY) } } - } for _, edge := range g.Edges { endpointLabels := []string{} From 5509621a43dfc5ccbf0717678807d21d1adcb463 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 28 Dec 2022 18:18:28 -0800 Subject: [PATCH 08/11] update tests --- .../dagre/board.exp.json | 20 ++++---- .../dagre/sketch.exp.svg | 28 +++++------ .../elk/board.exp.json | 16 +++---- .../elk/sketch.exp.svg | 28 +++++------ .../unnamed_only_height/dagre/board.exp.json | 16 +++---- .../unnamed_only_height/dagre/sketch.exp.svg | 2 +- .../unnamed_only_height/elk/board.exp.json | 18 ++++---- .../unnamed_only_height/elk/sketch.exp.svg | 2 +- .../unnamed_only_width/dagre/board.exp.json | 46 +++++++++---------- .../unnamed_only_width/dagre/sketch.exp.svg | 28 +++++------ .../unnamed_only_width/elk/board.exp.json | 34 +++++++------- .../unnamed_only_width/elk/sketch.exp.svg | 28 +++++------ 12 files changed, 133 insertions(+), 133 deletions(-) diff --git a/e2etests/testdata/regression/unnamed_class_table_code/dagre/board.exp.json b/e2etests/testdata/regression/unnamed_class_table_code/dagre/board.exp.json index f96e89a36..2d10adc2e 100644 --- a/e2etests/testdata/regression/unnamed_class_table_code/dagre/board.exp.json +++ b/e2etests/testdata/regression/unnamed_class_table_code/dagre/board.exp.json @@ -68,8 +68,8 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 5, - "labelHeight": 5, + "labelWidth": 0, + "labelHeight": 0, "zIndex": 0, "level": 1, "primaryAccentColor": "#0D32B2", @@ -84,7 +84,7 @@ "y": 468 }, "width": 208, - "height": 216, + "height": 186, "opacity": 1, "strokeDash": 0, "strokeWidth": 2, @@ -251,8 +251,8 @@ "italic": false, "bold": true, "underline": false, - "labelWidth": 64, - "labelHeight": 36, + "labelWidth": 59, + "labelHeight": 31, "zIndex": 0, "level": 1, "primaryAccentColor": "#0D32B2", @@ -264,7 +264,7 @@ "type": "code", "pos": { "x": 113, - "y": 784 + "y": 754 }, "width": 196, "height": 70, @@ -375,19 +375,19 @@ "route": [ { "x": 211, - "y": 684 + "y": 654 }, { "x": 211, - "y": 724 + "y": 694 }, { "x": 211, - "y": 744 + "y": 714 }, { "x": 211, - "y": 784 + "y": 754 } ], "isCurve": true, diff --git a/e2etests/testdata/regression/unnamed_class_table_code/dagre/sketch.exp.svg b/e2etests/testdata/regression/unnamed_class_table_code/dagre/sketch.exp.svg index 15c3051ff..2dc724baf 100644 --- a/e2etests/testdata/regression/unnamed_class_table_code/dagre/sketch.exp.svg +++ b/e2etests/testdata/regression/unnamed_class_table_code/dagre/sketch.exp.svg @@ -2,7 +2,7 @@