package layoutgraph
import (
"math"
"strings"
"github.com/pancsta/d2/d2layouts/d2talalayout/internal/invariant"
"github.com/pancsta/d2/lib/geo"
"github.com/pancsta/d2/lib/shape"
)
type Sequence struct {
Vessel *Node
Nodes []*Node
Graph *Graph
EdgeAbductions []*EdgeAbduction
Container *Node
}
func (s *Sequence ) findAbductedNodeByEdge (e *Edge ) *Node {
for _ , ea := range s .EdgeAbductions {
if e != ea .Edge {
continue
}
if ea .CurrentFrom == s .Vessel {
return ea .OriginallyFrom
}
if ea .CurrentTo == s .Vessel {
return ea .OriginallyTo
}
}
return nil
}
func (s *Sequence ) SyncGeometry () {
if err := s .SyncGeometryWithWork (unmeteredGroupGeometry ); err != nil {
panic (err )
}
}
func (s *Sequence ) SyncGeometryWithWork (work SharedWorkStepper ) error {
if work == nil {
return invariant .New ("sequence geometry requires work accounting" )
}
if err := work .Step (); err != nil {
return err
}
if s == nil || s .Vessel == nil {
return invariant .New ("sequence is missing its vessel" )
}
if err := s .resizeWithWork (work ); err != nil {
return err
}
return s .arrangeStepsWithWork (work )
}
func (s *Sequence ) resizeWithWork (work workStepper ) error {
width := 0.0
offset := 0.0
height := 0.0
for _ , n := range s .Nodes {
if err := work .Step (); err != nil {
return err
}
if n == nil {
return invariant .New ("sequence contains a nil step" )
}
width = math .Max (width , offset +math .Max (0 , n .Width ))
offset += SequenceAdvance (n .Width )
height = math .Max (height , math .Max (0 , n .Height ))
}
s .Vessel .Width = width
s .Vessel .Height = height
return nil
}
func (s *Sequence ) ArrangeSteps () {
if err := s .arrangeStepsWithWork (unmeteredGroupGeometry ); err != nil {
panic (err )
}
}
func (s *Sequence ) arrangeStepsWithWork (work workStepper ) error {
if s .Vessel .TopLeft == nil {
return work .Finish ()
}
tl := s .Vessel .TopLeft .Copy ()
for _ , n := range s .Nodes {
if err := work .Step (); err != nil {
return err
}
n .TopLeft = tl .Copy ()
tl .X += SequenceAdvance (n .Width )
}
return work .Finish ()
}
func (s *Sequence ) PlaceVessel () {
topLeft := geo .NewPoint (math .Inf (1 ), math .Inf (1 ))
for _ , node := range s .Nodes {
if node .TopLeft == nil {
return
}
topLeft .X = math .Min (topLeft .X , node .TopLeft .X )
topLeft .Y = math .Min (topLeft .Y , node .TopLeft .Y )
}
s .Vessel .TopLeft = topLeft
}
func SequenceAdvance (width float64 ) float64 {
if width <= 0 {
return 0
}
wedge := shape .STEP_WEDGE_WIDTH
if width <= wedge {
wedge = width / 2
}
return width - wedge
}
func (g *Graph ) SyncSequences () {
if len (g .Sequences ) == 0 {
return
}
sync := func (n *Node ) {
if sequence , is := g .Sequences [n ]; is {
sequence .SyncGeometry ()
}
}
for _ , n := range g .Nodes {
n .rdfsWalk (sync )
}
}
func (s *Sequence ) first () *Node {
return s .Nodes [0 ]
}
func (s *Sequence ) last () *Node {
return s .Nodes [len (s .Nodes )-1 ]
}
func (s *Sequence ) First () *Node { return s .first () }
func (s *Sequence ) Last () *Node { return s .last () }
func (s *Sequence ) isActive () bool {
return s != nil && s .Vessel .Graph != nil
}
func (s *Sequence ) DebugID () string {
nodeIDs := []string {}
for _ , n := range s .Nodes {
nodeIDs = append (nodeIDs , n .DebugID ())
}
return "[" + strings .Join (nodeIDs , ", " ) + "]"
}
The pages are generated with Golds v0.8.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .