Merge pull request #344 from alixander/sequence-notes

sequence diagram: notes
This commit is contained in:
Alexander Wang 2022-12-04 09:51:56 -08:00 committed by GitHub
commit a4e66f658a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 1380 additions and 22 deletions

View file

@ -20,6 +20,7 @@ type sequenceDiagram struct {
lifelines []*d2graph.Edge lifelines []*d2graph.Edge
actors []*d2graph.Object actors []*d2graph.Object
spans []*d2graph.Object spans []*d2graph.Object
notes []*d2graph.Object
// can be either actors or spans // can be either actors or spans
// rank: left to right position of actors/spans (spans have the same rank as their parents) // rank: left to right position of actors/spans (spans have the same rank as their parents)
@ -30,9 +31,43 @@ type sequenceDiagram struct {
minMessageRank map[*d2graph.Object]int minMessageRank map[*d2graph.Object]int
maxMessageRank map[*d2graph.Object]int maxMessageRank map[*d2graph.Object]int
messageYStep float64 yStep float64
actorXStep float64 actorXStep float64
maxActorHeight float64 maxActorHeight float64
verticalIndices map[string]int
}
func getObjEarliestLineNum(o *d2graph.Object) int {
min := int(math.MaxInt64)
for _, ref := range o.References {
if ref.MapKey == nil {
continue
}
min = go2.IntMin(min, ref.MapKey.Range.Start.Line)
}
return min
}
func getEdgeEarliestLineNum(e *d2graph.Edge) int {
min := int(math.MaxInt64)
for _, ref := range e.References {
if ref.MapKey == nil {
continue
}
min = go2.IntMin(min, ref.MapKey.Range.Start.Line)
}
return min
}
func hasEdge(o *d2graph.Object) bool {
for _, ref := range o.References {
if ref.MapKey != nil && len(ref.MapKey.Edges) > 0 {
return true
}
}
return false
} }
func newSequenceDiagram(actors []*d2graph.Object, messages []*d2graph.Edge) *sequenceDiagram { func newSequenceDiagram(actors []*d2graph.Object, messages []*d2graph.Edge) *sequenceDiagram {
@ -40,13 +75,15 @@ func newSequenceDiagram(actors []*d2graph.Object, messages []*d2graph.Edge) *seq
messages: messages, messages: messages,
actors: actors, actors: actors,
spans: nil, spans: nil,
notes: nil,
lifelines: nil, lifelines: nil,
objectRank: make(map[*d2graph.Object]int), objectRank: make(map[*d2graph.Object]int),
minMessageRank: make(map[*d2graph.Object]int), minMessageRank: make(map[*d2graph.Object]int),
maxMessageRank: make(map[*d2graph.Object]int), maxMessageRank: make(map[*d2graph.Object]int),
messageYStep: MIN_MESSAGE_DISTANCE, yStep: MIN_MESSAGE_DISTANCE,
actorXStep: MIN_ACTOR_DISTANCE, actorXStep: MIN_ACTOR_DISTANCE,
maxActorHeight: 0., maxActorHeight: 0.,
verticalIndices: make(map[string]int),
} }
for rank, actor := range actors { for rank, actor := range actors {
@ -63,21 +100,34 @@ func newSequenceDiagram(actors []*d2graph.Object, messages []*d2graph.Edge) *seq
queue := make([]*d2graph.Object, len(actor.ChildrenArray)) queue := make([]*d2graph.Object, len(actor.ChildrenArray))
copy(queue, actor.ChildrenArray) copy(queue, actor.ChildrenArray)
for len(queue) > 0 { for len(queue) > 0 {
span := queue[0] child := queue[0]
queue = queue[1:] queue = queue[1:]
// spans are always rectangles and have no labels // spans are children of actors that have edges
span.Attributes.Label = d2graph.Scalar{Value: ""} // notes are children of actors with no edges
span.Attributes.Shape = d2graph.Scalar{Value: shape.SQUARE_TYPE} if hasEdge(child) {
sd.spans = append(sd.spans, span) // spans have no labels
sd.objectRank[span] = rank // TODO why not? Spans should be able to
child.Attributes.Label = d2graph.Scalar{Value: ""}
child.Attributes.Shape = d2graph.Scalar{Value: shape.SQUARE_TYPE}
sd.spans = append(sd.spans, child)
sd.objectRank[child] = rank
} else {
sd.verticalIndices[child.AbsID()] = getObjEarliestLineNum(child)
// TODO change to page type when it doesn't look deformed
child.Attributes.Shape = d2graph.Scalar{Value: shape.SQUARE_TYPE}
sd.notes = append(sd.notes, child)
sd.objectRank[child] = rank
child.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter))
}
queue = append(queue, span.ChildrenArray...) queue = append(queue, child.ChildrenArray...)
} }
} }
for rank, message := range sd.messages { for rank, message := range sd.messages {
sd.messageYStep = math.Max(sd.messageYStep, float64(message.LabelDimensions.Height)) sd.verticalIndices[message.AbsID()] = getEdgeEarliestLineNum(message)
sd.yStep = math.Max(sd.yStep, float64(message.LabelDimensions.Height))
sd.setMinMaxMessageRank(message.Src, rank) sd.setMinMaxMessageRank(message.Src, rank)
sd.setMinMaxMessageRank(message.Dst, rank) sd.setMinMaxMessageRank(message.Dst, rank)
@ -89,7 +139,7 @@ func newSequenceDiagram(actors []*d2graph.Object, messages []*d2graph.Edge) *seq
sd.actorXStep = math.Max(sd.actorXStep, distributedLabelWidth+HORIZONTAL_PAD) sd.actorXStep = math.Max(sd.actorXStep, distributedLabelWidth+HORIZONTAL_PAD)
} }
sd.messageYStep += VERTICAL_PAD sd.yStep += VERTICAL_PAD
sd.maxActorHeight += VERTICAL_PAD sd.maxActorHeight += VERTICAL_PAD
if sd.root.LabelHeight != nil { if sd.root.LabelHeight != nil {
sd.maxActorHeight += float64(*sd.root.LabelHeight) sd.maxActorHeight += float64(*sd.root.LabelHeight)
@ -111,6 +161,7 @@ func (sd *sequenceDiagram) setMinMaxMessageRank(actor *d2graph.Object, rank int)
func (sd *sequenceDiagram) layout() { func (sd *sequenceDiagram) layout() {
sd.placeActors() sd.placeActors()
sd.placeSpans() sd.placeSpans()
sd.placeNotes()
sd.routeMessages() sd.routeMessages()
sd.addLifelineEdges() sd.addLifelineEdges()
} }
@ -142,7 +193,17 @@ func (sd *sequenceDiagram) placeActors() {
// │ // │
// │ // │
func (sd *sequenceDiagram) addLifelineEdges() { func (sd *sequenceDiagram) addLifelineEdges() {
endY := sd.getMessageY(len(sd.messages)) endY := 0.
for _, m := range sd.messages {
for _, p := range m.Route {
endY = math.Max(endY, p.Y)
}
}
for _, note := range sd.notes {
endY = math.Max(endY, note.TopLeft.Y+note.Height)
}
endY += sd.yStep
for _, actor := range sd.actors { for _, actor := range sd.actors {
actorBottom := actor.Center() actorBottom := actor.Center()
actorBottom.Y = actor.TopLeft.Y + actor.Height actorBottom.Y = actor.TopLeft.Y + actor.Height
@ -169,6 +230,31 @@ func (sd *sequenceDiagram) addLifelineEdges() {
} }
} }
func (sd *sequenceDiagram) placeNotes() {
rankToX := make(map[int]float64)
for _, actor := range sd.actors {
rankToX[sd.objectRank[actor]] = actor.Center().X
}
for i, note := range sd.notes {
verticalIndex := sd.verticalIndices[note.AbsID()]
y := sd.maxActorHeight + sd.yStep
for _, msg := range sd.messages {
if sd.verticalIndices[msg.AbsID()] < verticalIndex {
y += sd.yStep
}
}
for _, otherNote := range sd.notes[:i] {
y += otherNote.Height + sd.yStep
}
x := rankToX[sd.objectRank[note]] - (note.Width / 2.)
note.Box.TopLeft = geo.NewPoint(x, y)
note.ZIndex = 1
}
}
// placeSpans places spans over the object lifeline // placeSpans places spans over the object lifeline
// ┌──────────┐ // ┌──────────┐
// │ actor │ // │ actor │
@ -261,6 +347,13 @@ func (sd *sequenceDiagram) routeMessages() {
} }
messageY := sd.getMessageY(rank) messageY := sd.getMessageY(rank)
for _, note := range sd.notes {
if sd.verticalIndices[note.AbsID()] < sd.verticalIndices[message.AbsID()] {
messageY += note.Height + sd.yStep
}
}
message.Route = []*geo.Point{ message.Route = []*geo.Point{
geo.NewPoint(startX, messageY), geo.NewPoint(startX, messageY),
geo.NewPoint(endX, messageY), geo.NewPoint(endX, messageY),
@ -274,7 +367,7 @@ func (sd *sequenceDiagram) routeMessages() {
func (sd *sequenceDiagram) getMessageY(rank int) float64 { func (sd *sequenceDiagram) getMessageY(rank int) float64 {
// +1 so that the first message has the top padding for its label // +1 so that the first message has the top padding for its label
return ((float64(rank) + 1.) * sd.messageYStep) + sd.maxActorHeight return ((float64(rank) + 1.) * sd.yStep) + sd.maxActorHeight
} }
func (sd *sequenceDiagram) isActor(obj *d2graph.Object) bool { func (sd *sequenceDiagram) isActor(obj *d2graph.Object) bool {

View file

@ -1332,6 +1332,19 @@ z -> z: hello
label: hello label: hello
icon: https://icons.terrastruct.com/essentials/time.svg icon: https://icons.terrastruct.com/essentials/time.svg
} }
`,
},
{
name: "sequence_diagram_note",
script: `shape: sequence_diagram
a; b; c; d
a -> b
a.explanation
a.another explanation
b -> c
b."Some one who believes imaginary things\n appear right before your i's."
c -> b: okay
d."The earth is like a tiny grain of sand, only much, much heavier"
`, `,
}, },
} }

View file

@ -0,0 +1,592 @@
{
"name": "",
"shapes": [
{
"id": "a",
"type": "",
"pos": {
"x": 0,
"y": 50
},
"width": 150,
"height": 169,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#E3E9FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "a",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 12,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "b",
"type": "",
"pos": {
"x": 400,
"y": 52
},
"width": 150,
"height": 167,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#E3E9FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "b",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "c",
"type": "",
"pos": {
"x": 800,
"y": 52
},
"width": 150,
"height": 167,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "c",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "d",
"type": "",
"pos": {
"x": 1200,
"y": 52
},
"width": 150,
"height": 167,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#E3E9FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "d",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "a.explanation",
"type": "rectangle",
"pos": {
"x": -20,
"y": 479
},
"width": 190,
"height": 126,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#EDF0FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "explanation",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 90,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 1,
"level": 2
},
{
"id": "a.another explanation",
"type": "rectangle",
"pos": {
"x": -50,
"y": 735
},
"width": 250,
"height": 126,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#EDF0FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "another explanation",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 150,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 1,
"level": 2
},
{
"id": "b.\"Some one who believes imaginary things\\n appear right before your i's.\"",
"type": "rectangle",
"pos": {
"x": 278,
"y": 1121
},
"width": 393,
"height": 142,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#EDF0FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "Some one who believes imaginary things\n appear right before your i's.",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 293,
"labelHeight": 42,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 1,
"level": 2
},
{
"id": "d.The earth is like a tiny grain of sand, only much, much heavier",
"type": "rectangle",
"pos": {
"x": 1004,
"y": 1523
},
"width": 541,
"height": 126,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#EDF0FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "The earth is like a tiny grain of sand, only much, much heavier",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 441,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 1,
"level": 2
}
],
"connections": [
{
"id": "(a -> b)[0]",
"src": "a",
"srcArrow": "none",
"srcLabel": "",
"dst": "b",
"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": 75,
"y": 349
},
{
"x": 475,
"y": 349
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 2
},
{
"id": "(b -> c)[0]",
"src": "b",
"srcArrow": "none",
"srcLabel": "",
"dst": "c",
"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": 475,
"y": 991
},
{
"x": 875,
"y": 991
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 2
},
{
"id": "(c -> b)[0]",
"src": "c",
"srcArrow": "none",
"srcLabel": "",
"dst": "b",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "okay",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 33,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"labelPercentage": 0,
"route": [
{
"x": 875,
"y": 1393
},
{
"x": 475,
"y": 1393
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 2
},
{
"id": "(a -- )[0]",
"src": "a",
"srcArrow": "none",
"srcLabel": "",
"dst": "a-lifeline-end-2251863791",
"dstArrow": "none",
"dstLabel": "",
"opacity": 1,
"strokeDash": 8,
"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": 75,
"y": 219
},
{
"x": 75,
"y": 1779
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(b -- )[0]",
"src": "b",
"srcArrow": "none",
"srcLabel": "",
"dst": "b-lifeline-end-668380428",
"dstArrow": "none",
"dstLabel": "",
"opacity": 1,
"strokeDash": 8,
"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": 475,
"y": 219
},
{
"x": 475,
"y": 1779
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(c -- )[0]",
"src": "c",
"srcArrow": "none",
"srcLabel": "",
"dst": "c-lifeline-end-955173837",
"dstArrow": "none",
"dstLabel": "",
"opacity": 1,
"strokeDash": 8,
"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": 875,
"y": 219
},
{
"x": 875,
"y": 1779
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(d -- )[0]",
"src": "d",
"srcArrow": "none",
"srcLabel": "",
"dst": "d-lifeline-end-2106864010",
"dstArrow": "none",
"dstLabel": "",
"opacity": 1,
"strokeDash": 8,
"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": 1275,
"y": 219
},
{
"x": 1275,
"y": 1779
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 471 KiB

View file

@ -0,0 +1,592 @@
{
"name": "",
"shapes": [
{
"id": "a",
"type": "",
"pos": {
"x": 0,
"y": 50
},
"width": 150,
"height": 169,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#E3E9FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "a",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 12,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "b",
"type": "",
"pos": {
"x": 400,
"y": 52
},
"width": 150,
"height": 167,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#E3E9FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "b",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "c",
"type": "",
"pos": {
"x": 800,
"y": 52
},
"width": 150,
"height": 167,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "c",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "d",
"type": "",
"pos": {
"x": 1200,
"y": 52
},
"width": 150,
"height": 167,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#E3E9FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "d",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 13,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "a.explanation",
"type": "rectangle",
"pos": {
"x": -20,
"y": 479
},
"width": 190,
"height": 126,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#EDF0FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "explanation",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 90,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 1,
"level": 2
},
{
"id": "a.another explanation",
"type": "rectangle",
"pos": {
"x": -50,
"y": 735
},
"width": 250,
"height": 126,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#EDF0FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "another explanation",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 150,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 1,
"level": 2
},
{
"id": "b.\"Some one who believes imaginary things\\n appear right before your i's.\"",
"type": "rectangle",
"pos": {
"x": 278,
"y": 1121
},
"width": 393,
"height": 142,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#EDF0FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "Some one who believes imaginary things\n appear right before your i's.",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 293,
"labelHeight": 42,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 1,
"level": 2
},
{
"id": "d.The earth is like a tiny grain of sand, only much, much heavier",
"type": "rectangle",
"pos": {
"x": 1004,
"y": 1523
},
"width": 541,
"height": 126,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#EDF0FD",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"fields": null,
"methods": null,
"columns": null,
"label": "The earth is like a tiny grain of sand, only much, much heavier",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 441,
"labelHeight": 26,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 1,
"level": 2
}
],
"connections": [
{
"id": "(a -> b)[0]",
"src": "a",
"srcArrow": "none",
"srcLabel": "",
"dst": "b",
"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": 75,
"y": 349
},
{
"x": 475,
"y": 349
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 2
},
{
"id": "(b -> c)[0]",
"src": "b",
"srcArrow": "none",
"srcLabel": "",
"dst": "c",
"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": 475,
"y": 991
},
{
"x": 875,
"y": 991
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 2
},
{
"id": "(c -> b)[0]",
"src": "c",
"srcArrow": "none",
"srcLabel": "",
"dst": "b",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "okay",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 33,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"labelPercentage": 0,
"route": [
{
"x": 875,
"y": 1393
},
{
"x": 475,
"y": 1393
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 2
},
{
"id": "(a -- )[0]",
"src": "a",
"srcArrow": "none",
"srcLabel": "",
"dst": "a-lifeline-end-2251863791",
"dstArrow": "none",
"dstLabel": "",
"opacity": 1,
"strokeDash": 8,
"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": 75,
"y": 219
},
{
"x": 75,
"y": 1779
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(b -- )[0]",
"src": "b",
"srcArrow": "none",
"srcLabel": "",
"dst": "b-lifeline-end-668380428",
"dstArrow": "none",
"dstLabel": "",
"opacity": 1,
"strokeDash": 8,
"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": 475,
"y": 219
},
{
"x": 475,
"y": 1779
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(c -- )[0]",
"src": "c",
"srcArrow": "none",
"srcLabel": "",
"dst": "c-lifeline-end-955173837",
"dstArrow": "none",
"dstLabel": "",
"opacity": 1,
"strokeDash": 8,
"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": 875,
"y": 219
},
{
"x": 875,
"y": 1779
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(d -- )[0]",
"src": "d",
"srcArrow": "none",
"srcLabel": "",
"dst": "d-lifeline-end-2106864010",
"dstArrow": "none",
"dstLabel": "",
"opacity": 1,
"strokeDash": 8,
"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": 1275,
"y": 219
},
{
"x": 1275,
"y": 1779
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 471 KiB