This commit is contained in:
Gavin Nishizawa 2023-09-15 22:07:06 -07:00
parent e83ac4c3ac
commit b7791c83ea
No known key found for this signature in database
GPG key ID: AE3B177777CE55CD
8 changed files with 810 additions and 757 deletions

View file

@ -1925,7 +1925,7 @@ func (g *Graph) PrintString() string {
buf := &bytes.Buffer{}
fmt.Fprint(buf, "Objects: [")
for _, obj := range g.Objects {
fmt.Fprintf(buf, "%#v @(%v)", obj.AbsID(), obj.TopLeft.ToString())
fmt.Fprintf(buf, "%v, ", obj.AbsID())
}
fmt.Fprint(buf, "]")
return buf.String()

View file

@ -47,6 +47,164 @@ func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) d
}
}
func Layout2(ctx context.Context, g *d2graph.Graph) error {
obj := g.Root
gd, err := layoutGrid(g, obj)
if err != nil {
return err
}
// obj.Children = make(map[string]*d2graph.Object)
// obj.ChildrenArray = nil
if obj.Box != nil {
// CONTAINER_PADDING is default, but use gap value if set
horizontalPadding, verticalPadding := CONTAINER_PADDING, CONTAINER_PADDING
if obj.GridGap != nil || obj.HorizontalGap != nil {
horizontalPadding = gd.horizontalGap
}
if obj.GridGap != nil || obj.VerticalGap != nil {
verticalPadding = gd.verticalGap
}
// size shape according to grid
obj.SizeToContent(gd.width, gd.height, float64(2*horizontalPadding), float64(2*verticalPadding))
// compute where the grid should be placed inside shape
s := obj.ToShape()
innerBox := s.GetInnerBox()
if innerBox.TopLeft.X != 0 || innerBox.TopLeft.Y != 0 {
gd.shift(innerBox.TopLeft.X, innerBox.TopLeft.Y)
}
// compute how much space the label and icon occupy
var occupiedWidth, occupiedHeight float64
if obj.Icon != nil {
iconSpace := float64(d2target.MAX_ICON_SIZE + 2*label.PADDING)
occupiedWidth = iconSpace
occupiedHeight = iconSpace
}
var dx, dy float64
if obj.LabelDimensions.Height != 0 {
occupiedHeight = math.Max(
occupiedHeight,
float64(obj.LabelDimensions.Height)+2*label.PADDING,
)
}
if obj.LabelDimensions.Width != 0 {
// . ├────┤───────├────┤
// . icon label icon
// with an icon in top left we need 2x the space to fit the label in the center
occupiedWidth *= 2
occupiedWidth += float64(obj.LabelDimensions.Width) + 2*label.PADDING
if occupiedWidth > obj.Width {
dx = (occupiedWidth - obj.Width) / 2
obj.Width = occupiedWidth
}
}
// also check for grid cells with outside top labels or icons
// the first grid object is at the top (and always exists)
topY := gd.objects[0].TopLeft.Y
highestOutside := topY
for _, o := range gd.objects {
// we only want to compute label positions for objects at the top of the grid
if o.TopLeft.Y > topY {
if gd.rowDirected {
// if the grid is rowDirected (row1, row2, etc) we can stop after finishing the first row
break
} else {
// otherwise we continue until the next column
continue
}
}
if o.LabelPosition != nil {
labelPosition := label.Position(*o.LabelPosition)
if labelPosition.IsOutside() {
labelTL := o.GetLabelTopLeft()
if labelTL.Y < highestOutside {
highestOutside = labelTL.Y
}
}
}
if o.IconPosition != nil {
switch label.Position(*o.IconPosition) {
case label.OutsideTopLeft, label.OutsideTopCenter, label.OutsideTopRight:
iconSpace := float64(d2target.MAX_ICON_SIZE + label.PADDING)
if topY-iconSpace < highestOutside {
highestOutside = topY - iconSpace
}
}
}
}
if highestOutside < topY {
occupiedHeight += topY - highestOutside + 2*label.PADDING
}
if occupiedHeight > float64(verticalPadding) {
// if the label doesn't fit within the padding, we need to add more
dy = occupiedHeight - float64(verticalPadding)
obj.Height += dy
}
// we need to center children if we have to expand to fit the container label
if dx != 0 || dy != 0 {
gd.shift(dx, dy)
}
}
if obj.HasLabel() {
obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
}
if obj.Icon != nil {
obj.IconPosition = go2.Pointer(string(label.InsideTopLeft))
}
// simple straight line edge routing between grid objects
for _, e := range g.Edges {
// edgeOrder[e.AbsID()] = i
if !e.Src.Parent.IsDescendantOf(obj) && !e.Dst.Parent.IsDescendantOf(obj) {
continue
}
// if edge is within grid, remove it from outer layout
gd.edges = append(gd.edges, e)
// edgeToRemove[e] = struct{}{}
if e.Src.Parent != obj || e.Dst.Parent != obj {
continue
}
// if edge is grid child, use simple routing
e.Route = []*geo.Point{e.Src.Center(), e.Dst.Center()}
e.TraceToShape(e.Route, 0, 1)
if e.Label.Value != "" {
e.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter))
}
}
if g.Root.IsGridDiagram() && len(g.Root.ChildrenArray) != 0 {
g.Root.TopLeft = geo.NewPoint(0, 0)
}
obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
horizontalPadding, verticalPadding := CONTAINER_PADDING, CONTAINER_PADDING
if obj.GridGap != nil || obj.HorizontalGap != nil {
horizontalPadding = gd.horizontalGap
}
if obj.GridGap != nil || obj.VerticalGap != nil {
verticalPadding = gd.verticalGap
}
// shift the grid from (0, 0)
gd.shift(
obj.TopLeft.X+float64(horizontalPadding),
obj.TopLeft.Y+float64(verticalPadding),
)
gd.cleanup(obj, g)
return nil
}
func withoutGridDiagrams(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) (gridDiagrams map[string]*gridDiagram, objectOrder, edgeOrder map[string]int, err error) {
toRemove := make(map[*d2graph.Object]struct{})
edgeToRemove := make(map[*d2graph.Edge]struct{})

View file

@ -5,11 +5,13 @@ import (
"math"
"strings"
"cdr.dev/slog"
"oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/d2layouts/d2grid"
"oss.terrastruct.com/d2/d2layouts/d2near"
"oss.terrastruct.com/d2/d2layouts/d2sequence"
"oss.terrastruct.com/d2/lib/geo"
"oss.terrastruct.com/d2/lib/log"
)
type DiagramType string
@ -33,6 +35,7 @@ func (gi GraphInfo) isDefault() bool {
func LayoutNested(ctx context.Context, g *d2graph.Graph, graphInfo GraphInfo, coreLayout d2graph.LayoutGraph) geo.Spacing {
log.Warn(ctx, "ln info", slog.F("gi", graphInfo))
// Before we can layout these nodes, we need to handle all nested diagrams first.
extracted := make(map[*d2graph.Object]*d2graph.Graph)
extractedInfo := make(map[*d2graph.Object]GraphInfo)
@ -53,28 +56,39 @@ func LayoutNested(ctx context.Context, g *d2graph.Graph, graphInfo GraphInfo, co
for _, child := range queue {
if gi := NestedGraphInfo(child); !gi.isDefault() {
extractedInfo[child] = gi
// log.Warn(ctx, "nested", slog.F("child", child.AbsID()), slog.F("gi", gi))
var nestedGraph *d2graph.Graph
if gi.IsConstantNear {
nestedGraph = ExtractSelf(child)
} else {
// There is a nested diagram here, so extract its contents and process in the same way
nestedGraph = ExtractDescendants(child)
}
// There is a nested diagram here, so extract its contents and process in the same way
nestedGraph := ExtractDescendants(child)
// Layout of nestedGraph is completed
// log.Error(ctx, "recurse", slog.F("child", child.AbsID()), slog.F("level", child.Level()))
spacing := LayoutNested(ctx, nestedGraph, gi, coreLayout)
if !gi.IsConstantNear {
// Fit child to size of nested layout
FitToGraph(child, nestedGraph, spacing)
log.Warn(ctx, "fitting child", slog.F("child", child.AbsID()))
// Fit child to size of nested layout
FitToGraph(child, nestedGraph, spacing)
var nearGraph *d2graph.Graph
if gi.IsConstantNear {
nearGraph = ExtractSelf(child)
child.TopLeft = geo.NewPoint(0, 0)
child.Width = nestedGraph.Root.Width
child.Width = nestedGraph.Root.Height
}
// if gi.IsConstantNear {
// // FitToGraph(child, nestedGraph, spacing)
// if nestedGraph.Root.Box != nil {
// child.Width = nestedGraph.Root.Width
// child.Height = nestedGraph.Root.Height
// }
// }
// We will restore the contents after running layout with child as the placeholder
if gi.IsConstantNear {
constantNears = append(constantNears, nestedGraph)
} else {
extracted[child] = nestedGraph
constantNears = append(constantNears, nearGraph)
}
extracted[child] = nestedGraph
} else if len(child.Children) > 0 {
queue = append(queue, child.ChildrenArray...)
}
@ -89,17 +103,21 @@ func LayoutNested(ctx context.Context, g *d2graph.Graph, graphInfo GraphInfo, co
switch graphInfo.DiagramType {
case GridDiagram:
layoutWithGrids := d2grid.Layout(ctx, g, coreLayout)
if err = layoutWithGrids(ctx, g); err != nil {
log.Warn(ctx, "layout grid", slog.F("rootlevel", g.RootLevel), slog.F("shapes", g.PrintString()))
// layoutWithGrids := d2grid.Layout2(ctx, g, coreLayout)
// layoutWithGrids(ctx, g)
if err = d2grid.Layout2(ctx, g); err != nil {
panic(err)
}
case SequenceDiagram:
log.Warn(ctx, "layout sequence", slog.F("rootlevel", g.RootLevel), slog.F("shapes", g.PrintString()))
err = d2sequence.Layout2(ctx, g, coreLayout)
if err != nil {
panic(err)
}
default:
log.Warn(ctx, "default layout", slog.F("rootlevel", g.RootLevel), slog.F("shapes", g.PrintString()))
err := coreLayout(ctx, g)
if err != nil {
panic(err)
@ -109,14 +127,6 @@ func LayoutNested(ctx context.Context, g *d2graph.Graph, graphInfo GraphInfo, co
}
spacing := LayoutDiagram(ctx, g, graphInfo, coreLayout)
// With the layout set, inject all the extracted graphs
for n, nestedGraph := range extracted {
if !extractedInfo[n].IsConstantNear {
InjectNested(n, nestedGraph)
PositionNested(n, nestedGraph)
}
}
// if there are
if len(constantNears) > 0 {
err := d2near.Layout(ctx, g, constantNears)
@ -125,6 +135,15 @@ func LayoutNested(ctx context.Context, g *d2graph.Graph, graphInfo GraphInfo, co
}
}
// With the layout set, inject all the extracted graphs
for n, nestedGraph := range extracted {
// if !extractedInfo[n].IsConstantNear {
InjectNested(n, nestedGraph)
PositionNested(n, nestedGraph)
// }
}
log.Warn(ctx, "done", slog.F("rootlevel", g.RootLevel))
return spacing
}
@ -152,6 +171,7 @@ func NestedGraphInfo(obj *d2graph.Object) (gi GraphInfo) {
func ExtractSelf(container *d2graph.Object) *d2graph.Graph {
nestedGraph := d2graph.NewGraph()
nestedGraph.RootLevel = int(container.Level()) - 1
// nestedGraph.Root.Box = &geo.Box{}
// separate out nested edges
g := container.Graph
@ -255,13 +275,16 @@ func InjectNested(container *d2graph.Object, nestedGraph *d2graph.Graph) {
g.Objects = append(g.Objects, nestedGraph.Objects...)
g.Edges = append(g.Edges, nestedGraph.Edges...)
if g.Root.LabelPosition != nil {
container.LabelPosition = g.Root.LabelPosition
}
}
func PositionNested(container *d2graph.Object, nestedGraph *d2graph.Graph) {
tl, _ := boundingBox(nestedGraph)
// _, _ := boundingBox(nestedGraph)
// Note: assumes nestedGraph's layout has contents positioned relative to 0,0
dx := container.TopLeft.X - tl.X
dy := container.TopLeft.Y - tl.Y
dx := container.TopLeft.X //- tl.X
dy := container.TopLeft.Y //- tl.Y
for _, o := range nestedGraph.Objects {
o.TopLeft.X += dx
o.TopLeft.Y += dy
@ -279,6 +302,9 @@ func boundingBox(g *d2graph.Graph) (tl, br *geo.Point) {
br = geo.NewPoint(math.Inf(-1), math.Inf(-1))
for _, obj := range g.Objects {
if obj.TopLeft == nil {
panic(obj.AbsID())
}
tl.X = math.Min(tl.X, obj.TopLeft.X)
tl.Y = math.Min(tl.Y, obj.TopLeft.Y)
br.X = math.Max(br.X, obj.TopLeft.X+obj.Width)
@ -289,9 +315,17 @@ func boundingBox(g *d2graph.Graph) (tl, br *geo.Point) {
}
func FitToGraph(container *d2graph.Object, nestedGraph *d2graph.Graph, padding geo.Spacing) {
tl, br := boundingBox(nestedGraph)
container.Width = padding.Left + br.X - tl.X + padding.Right
container.Height = padding.Top + br.Y - tl.Y + padding.Bottom
var width, height float64
// if nestedGraph.Root.Box != nil {
width = nestedGraph.Root.Width
height = nestedGraph.Root.Height
if width == 0 || height == 0 {
tl, br := boundingBox(nestedGraph)
width = br.X - tl.X
height = br.Y - tl.Y
}
container.Width = padding.Left + width + padding.Right
container.Height = padding.Top + height + padding.Bottom
}
// func LayoutDiagram(ctx context.Context, g *d2graph.Graph, graphInfo GraphInfo, coreLayout d2graph.LayoutGraph) geo.Spacing {

View file

@ -22,12 +22,12 @@ b: {
1 -> 2
# TODO This should work
# near: bottom-left
near: bottom-right
#
2: {
# TODO compile error grid on sequence actor
grid-rows: 3
# grid-rows: 3
x
y
z
@ -36,7 +36,7 @@ b: {
1: {
x: {
# TODO compile error grid in sequence (anywhere)
grid-rows: 3
# grid-rows: 3
u
v
w

View file

@ -10,8 +10,8 @@
"x": 0,
"y": 0
},
"width": 274,
"height": 1394,
"width": 699,
"height": 393,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
@ -40,7 +40,7 @@
"underline": false,
"labelWidth": 13,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
@ -48,8 +48,8 @@
"id": "c",
"type": "rectangle",
"pos": {
"x": 334,
"y": 664
"x": 759,
"y": 164
},
"width": 53,
"height": 66,
@ -89,11 +89,11 @@
"id": "b.1",
"type": "rectangle",
"pos": {
"x": 12,
"y": 88
"x": 0,
"y": 0
},
"width": 100,
"height": 66,
"width": 617,
"height": 187,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -122,7 +122,7 @@
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"labelPosition": "OUTSIDE_TOP_CENTER",
"zIndex": 0,
"level": 2
},
@ -130,10 +130,10 @@
"id": "b.2",
"type": "rectangle",
"pos": {
"x": 162,
"y": 88
"x": 422,
"y": 327
},
"width": 100,
"width": 277,
"height": 66,
"opacity": 1,
"strokeDash": 0,
@ -168,19 +168,19 @@
"level": 2
},
{
"id": "b.2.x",
"type": "page",
"id": "b.1.x",
"type": "rectangle",
"pos": {
"x": 186,
"y": 294
"x": 30,
"y": 31
},
"width": 52,
"height": 66,
"width": 342,
"height": 126,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"fill": "B4",
"stroke": "B1",
"shadow": false,
"3d": false,
@ -204,138 +204,16 @@
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"level": 3
},
{
"id": "b.2.y",
"type": "page",
"pos": {
"x": 185,
"y": 430
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "y",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"level": 3
},
{
"id": "b.2.z",
"type": "page",
"pos": {
"x": 186,
"y": 566
},
"width": 52,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "z",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"level": 3
},
{
"id": "b.1.x",
"type": "rectangle",
"pos": {
"x": 56,
"y": 692
},
"width": 12,
"height": 358,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B4",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"zIndex": 2,
"labelPosition": "OUTSIDE_TOP_CENTER",
"zIndex": 0,
"level": 3
},
{
"id": "b.1.x.u",
"type": "page",
"type": "rectangle",
"pos": {
"x": 36,
"y": 702
"x": 60,
"y": 61
},
"width": 52,
"height": 66,
@ -368,15 +246,15 @@
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"zIndex": 0,
"level": 4
},
{
"id": "b.1.x.v",
"type": "page",
"type": "rectangle",
"pos": {
"x": 35,
"y": 838
"x": 172,
"y": 61
},
"width": 53,
"height": 66,
@ -409,15 +287,15 @@
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"zIndex": 0,
"level": 4
},
{
"id": "b.1.x.w",
"type": "page",
"type": "rectangle",
"pos": {
"x": 33,
"y": 974
"x": 285,
"y": 61
},
"width": 57,
"height": 66,
@ -450,15 +328,15 @@
"labelWidth": 12,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"zIndex": 0,
"level": 4
},
{
"id": "b.1.y",
"type": "page",
"type": "rectangle",
"pos": {
"x": 35,
"y": 1110
"x": 534,
"y": 61
},
"width": 53,
"height": 66,
@ -491,15 +369,15 @@
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"zIndex": 0,
"level": 3
},
{
"id": "b.1.z",
"type": "page",
"type": "rectangle",
"pos": {
"x": 36,
"y": 1246
"x": 422,
"y": 61
},
"width": 52,
"height": 66,
@ -532,18 +410,141 @@
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"zIndex": 0,
"level": 3
},
{
"id": "b.2.x",
"type": "rectangle",
"pos": {
"x": 422,
"y": 327
},
"width": 52,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "x",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 3
},
{
"id": "b.2.y",
"type": "rectangle",
"pos": {
"x": 534,
"y": 327
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "y",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 3
},
{
"id": "b.2.z",
"type": "rectangle",
"pos": {
"x": 647,
"y": 327
},
"width": 52,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "z",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 3
},
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 407,
"y": -478
"x": 832,
"y": -444
},
"width": 345,
"height": 458,
"width": 285,
"height": 398,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -580,10 +581,10 @@
"id": "a.1",
"type": "rectangle",
"pos": {
"x": 467,
"y": -418
"x": 892,
"y": -384
},
"width": 225,
"width": 165,
"height": 66,
"opacity": 1,
"strokeDash": 0,
@ -621,10 +622,10 @@
"id": "a.2",
"type": "rectangle",
"pos": {
"x": 467,
"y": -312
"x": 892,
"y": -278
},
"width": 225,
"width": 165,
"height": 66,
"opacity": 1,
"strokeDash": 0,
@ -662,11 +663,11 @@
"id": "a.3",
"type": "sequence_diagram",
"pos": {
"x": 467,
"y": -206
"x": 892,
"y": -172
},
"width": 225,
"height": 126,
"width": 165,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
@ -695,7 +696,7 @@
"underline": false,
"labelWidth": 11,
"labelHeight": 31,
"labelPosition": "OUTSIDE_TOP_CENTER",
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
@ -703,8 +704,8 @@
"id": "a.3.x",
"type": "rectangle",
"pos": {
"x": 497,
"y": -176
"x": 892,
"y": -172
},
"width": 52,
"height": 66,
@ -744,8 +745,8 @@
"id": "a.3.y",
"type": "rectangle",
"pos": {
"x": 609,
"y": -176
"x": 1004,
"y": -172
},
"width": 53,
"height": 66,
@ -808,94 +809,27 @@
"labelPercentage": 0,
"route": [
{
"x": 62,
"y": 224
"x": 560.5,
"y": 187
},
{
"x": 212,
"y": 224
"x": 560.5,
"y": 259
},
{
"x": 560.5,
"y": 287
},
{
"x": 560.5,
"y": 327
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 4
},
{
"id": "(b.1 -- )[0]",
"src": "b.1",
"srcArrow": "none",
"dst": "1-lifeline-end-1719232319",
"dstArrow": "none",
"opacity": 1,
"strokeDash": 6,
"strokeWidth": 2,
"stroke": "B2",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 62,
"y": 154
},
{
"x": 62,
"y": 1382
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 1
},
{
"id": "(b.2 -- )[0]",
"src": "b.2",
"srcArrow": "none",
"dst": "2-lifeline-end-1739547740",
"dstArrow": "none",
"opacity": 1,
"strokeDash": 6,
"strokeWidth": 2,
"stroke": "B2",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 212,
"y": 154
},
{
"x": 212,
"y": 1382
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 1
"zIndex": 0
}
],
"root": {

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -10,8 +10,8 @@
"x": 12,
"y": 12
},
"width": 274,
"height": 1394,
"width": 547,
"height": 402,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
@ -40,7 +40,7 @@
"underline": false,
"labelWidth": 13,
"labelHeight": 36,
"labelPosition": "INSIDE_TOP_CENTER",
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
@ -48,8 +48,8 @@
"id": "c",
"type": "rectangle",
"pos": {
"x": 306,
"y": 676
"x": 579,
"y": 180
},
"width": 53,
"height": 66,
@ -89,11 +89,11 @@
"id": "b.1",
"type": "rectangle",
"pos": {
"x": 24,
"y": 100
"x": 12,
"y": 12
},
"width": 100,
"height": 66,
"width": 547,
"height": 266,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -122,7 +122,7 @@
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 2
},
@ -130,10 +130,10 @@
"id": "b.2",
"type": "rectangle",
"pos": {
"x": 174,
"y": 100
"x": 187,
"y": 348
},
"width": 100,
"width": 197,
"height": 66,
"opacity": 1,
"strokeDash": 0,
@ -168,19 +168,19 @@
"level": 2
},
{
"id": "b.2.x",
"type": "page",
"id": "b.1.x",
"type": "rectangle",
"pos": {
"x": 198,
"y": 306
"x": 62,
"y": 62
},
"width": 52,
"height": 66,
"width": 302,
"height": 166,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"fill": "B4",
"stroke": "B1",
"shadow": false,
"3d": false,
@ -204,138 +204,16 @@
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"level": 3
},
{
"id": "b.2.y",
"type": "page",
"pos": {
"x": 197,
"y": 442
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "y",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"level": 3
},
{
"id": "b.2.z",
"type": "page",
"pos": {
"x": 198,
"y": 578
},
"width": 52,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "z",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"level": 3
},
{
"id": "b.1.x",
"type": "rectangle",
"pos": {
"x": 68,
"y": 704
},
"width": 12,
"height": 358,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B4",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"zIndex": 2,
"labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 3
},
{
"id": "b.1.x.u",
"type": "page",
"type": "rectangle",
"pos": {
"x": 48,
"y": 714
"x": 112,
"y": 112
},
"width": 52,
"height": 66,
@ -368,15 +246,15 @@
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"zIndex": 0,
"level": 4
},
{
"id": "b.1.x.v",
"type": "page",
"type": "rectangle",
"pos": {
"x": 47,
"y": 850
"x": 184,
"y": 112
},
"width": 53,
"height": 66,
@ -409,15 +287,15 @@
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"zIndex": 0,
"level": 4
},
{
"id": "b.1.x.w",
"type": "page",
"type": "rectangle",
"pos": {
"x": 45,
"y": 986
"x": 257,
"y": 112
},
"width": 57,
"height": 66,
@ -450,15 +328,15 @@
"labelWidth": 12,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"zIndex": 0,
"level": 4
},
{
"id": "b.1.y",
"type": "page",
"type": "rectangle",
"pos": {
"x": 47,
"y": 1122
"x": 384,
"y": 112
},
"width": 53,
"height": 66,
@ -491,15 +369,15 @@
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"zIndex": 0,
"level": 3
},
{
"id": "b.1.z",
"type": "page",
"type": "rectangle",
"pos": {
"x": 48,
"y": 1258
"x": 457,
"y": 112
},
"width": 52,
"height": 66,
@ -532,18 +410,141 @@
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"zIndex": 0,
"level": 3
},
{
"id": "b.2.x",
"type": "rectangle",
"pos": {
"x": 187,
"y": 348
},
"width": 52,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "x",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 3
},
{
"id": "b.2.y",
"type": "rectangle",
"pos": {
"x": 259,
"y": 348
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "y",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 3
},
{
"id": "b.2.z",
"type": "rectangle",
"pos": {
"x": 332,
"y": 348
},
"width": 52,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "z",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 3
},
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 379,
"y": -506
"x": 652,
"y": -406
},
"width": 345,
"height": 498,
"width": 245,
"height": 398,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@ -580,10 +581,10 @@
"id": "a.1",
"type": "rectangle",
"pos": {
"x": 439,
"y": -446
"x": 712,
"y": -346
},
"width": 225,
"width": 125,
"height": 66,
"opacity": 1,
"strokeDash": 0,
@ -621,10 +622,10 @@
"id": "a.2",
"type": "rectangle",
"pos": {
"x": 439,
"y": -340
"x": 712,
"y": -240
},
"width": 225,
"width": 125,
"height": 66,
"opacity": 1,
"strokeDash": 0,
@ -662,11 +663,11 @@
"id": "a.3",
"type": "sequence_diagram",
"pos": {
"x": 439,
"y": -234
"x": 712,
"y": -134
},
"width": 225,
"height": 166,
"width": 125,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 0,
@ -695,7 +696,7 @@
"underline": false,
"labelWidth": 11,
"labelHeight": 31,
"labelPosition": "INSIDE_TOP_CENTER",
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 2
},
@ -703,8 +704,8 @@
"id": "a.3.x",
"type": "rectangle",
"pos": {
"x": 489,
"y": -184
"x": 712,
"y": -134
},
"width": 52,
"height": 66,
@ -744,8 +745,8 @@
"id": "a.3.y",
"type": "rectangle",
"pos": {
"x": 561,
"y": -184
"x": 784,
"y": -134
},
"width": 53,
"height": 66,
@ -808,94 +809,18 @@
"labelPercentage": 0,
"route": [
{
"x": 74,
"y": 236
"x": 285.5,
"y": 278
},
{
"x": 224,
"y": 236
"x": 285.5,
"y": 348
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 4
},
{
"id": "(b.1 -- )[0]",
"src": "b.1",
"srcArrow": "none",
"dst": "1-lifeline-end-1719232319",
"dstArrow": "none",
"opacity": 1,
"strokeDash": 6,
"strokeWidth": 2,
"stroke": "B2",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 74,
"y": 166
},
{
"x": 74,
"y": 1394
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 1
},
{
"id": "(b.2 -- )[0]",
"src": "b.2",
"srcArrow": "none",
"dst": "2-lifeline-end-1739547740",
"dstArrow": "none",
"opacity": 1,
"strokeDash": 6,
"strokeWidth": 2,
"stroke": "B2",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 224,
"y": 166
},
{
"x": 224,
"y": 1394
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 1
"zIndex": 0
}
],
"root": {

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 20 KiB