// Copyright (c) 2010, 2019 Kiel University and others.
// Copyright (c) 2015, 2020 Kiel University and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0.
//
// SPDX-License-Identifier: EPL-2.0

// Package fixed implements org.eclipse.elk.fixed from ELK 0.8.1.
package fixed import ( ) type Provider struct{} func ( *core.AlgorithmRegistry) error { return .Register(core.AlgorithmData{ ID: "org.eclipse.elk.fixed", Create: func() core.LayoutProvider { return &Provider{} }, KnownOptions: []string{ basicoptions.FixedPadding.ID, basicoptions.Position.ID, basicoptions.BendPoints.ID, core.NodeSizeConstraints.ID, core.NodeSizeMinimum.ID, basicoptions.NodeSizeFixedGraphSize.ID, }, }) } func (*Provider) ( *graph.Model, graph.NodeID, core.ProgressMonitor) error { := .Node() := graph.Get(&.Properties, basicoptions.EdgeRouting) , := 0.0, 0.0 for , := range .Children { := .Node() if , := graph.TryGet(&.Properties, basicoptions.Position); { .Shape.SetLocation(.X, .Y) if contains(graph.Get(&.Properties, core.NodeSizeConstraints), "MINIMUM_SIZE") { := graph.Get(&.Properties, core.NodeSizeMinimum) if .X > 0 && .Y > 0 { elkutil.ResizeNode(, , .X, .Y, true, true) } } } = math.Max(, .Shape.X+.Shape.Width) = math.Max(, .Shape.Y+.Shape.Height) for , := range .Labels { := .Label() applyPosition(&.Shape, &.Properties) = math.Max(, .Shape.X+.Shape.X+.Shape.Width) = math.Max(, .Shape.Y+.Shape.Y+.Shape.Height) } for , := range .Ports { := .Port() applyPosition(&.Shape, &.Properties) := .Shape.X + .Shape.X := .Shape.Y + .Shape.Y = math.Max(, +.Shape.Width) = math.Max(, +.Shape.Height) for , := range .Labels { := .Label() applyPosition(&.Shape, &.Properties) = math.Max(, +.Shape.X+.Shape.Width) = math.Max(, +.Shape.Y+.Shape.Height) } } for , := range elkutil.AllOutgoingEdges(, ) { , := processEdge(, ) if != nil { return } = math.Max(, .X) = math.Max(, .Y) } for , := range elkutil.AllIncomingEdges(, ) { := .Edge() if len(.Sources) == 0 { continue } := .ShapeNode(.Sources[0]) := .Node().Parent if == nil || * != { , := processEdge(, ) if != nil { return } = math.Max(, .X) = math.Max(, .Y) } } } if == "ORTHOGONAL" { for , := range .Children { for , := range elkutil.AllOutgoingEdges(, ) { , := elkutil.DetermineJunctionPoints(, ) if != nil { return } if len() == 0 { graph.Unset(&.Edge().Properties, core.JunctionPoints) } else { graph.Set(&.Edge().Properties, core.JunctionPoints, ) } } } } if !graph.Get(&.Properties, basicoptions.NodeSizeFixedGraphSize) { := graph.Get(&.Properties, basicoptions.FixedPadding) elkutil.ResizeNode(, , +.Left+.Right, +.Top+.Bottom, true, true) } return nil } func applyPosition( *graph.Shape, *graph.PropertyMap) { if , := graph.TryGet(, basicoptions.Position); { .SetLocation(.X, .Y) } } func processEdge( *graph.Model, graph.EdgeID) (geometry.Point, error) { := .Edge() if len(.Sources) == 0 || len(.Targets) == 0 { return geometry.Point{}, nil } := .Node(.ShapeNode(.Sources[0])).Parent := .Node(.ShapeNode(.Targets[0])).Parent := != nil && != nil && * == * := geometry.Point{} if , := graph.TryGet(&.Properties, basicoptions.BendPoints); && len() >= 2 { if len(.Sections) == 0 { .AddSection() } else if len(.Sections) > 1 { // The 0.8.1 source attempts ListIterator.remove before next, // which raises IllegalStateException for this invalid state. return geometry.Point{}, fmt.Errorf("fixed edge %q has multiple sections", .Identifier) } elkutil.ApplyVectorChain(, .Sections[0], ) } if { for , := range .Sections { for , := range .Section().BendPoints { .X = math.Max(.X, .X) .Y = math.Max(.Y, .Y) } } } for , := range .Labels { := .Label() applyPosition(&.Shape, &.Properties) if { .X = math.Max(.X, .Shape.X+.Shape.Width) .Y = math.Max(.Y, .Shape.Y+.Shape.Height) } } return , nil } func contains( []string, string) bool { for , := range { if == { return true } } return false }