// Copyright 2025 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
/// Apply a layout patch to an immutable `GraphInput`.
///|
fn apply_box_to_object(
obj : ObjectInput,
nodes : Map[String, Box],
node_labels : Map[String, Box],
) -> ObjectInput {
let layout_box = match nodes.get(obj.abs_id_syntax) {
Some(b) => Some(b)
None => obj.box
}
let layout_label_box = match node_labels.get(obj.abs_id_syntax) {
Some(b) => Some(b)
None => obj.label_box
}
{
..obj,
box: apply_locked_position(obj, layout_box),
label_box: layout_label_box,
}
}
///|
fn apply_locked_position(obj : ObjectInput, box : Box?) -> Box? {
match box {
Some(b) => {
let x = match obj.left {
Some(v) => v.to_double()
None => b.x
}
let y = match obj.top {
Some(v) => v.to_double()
None => b.y
}
Some(Box::new(x, y, b.width, b.height))
}
None => None
}
}
///|
fn apply_route_to_edge(
edge : EdgeInput,
routes : Map[Int, Array[Point]],
edge_bend_points : Map[Int, Array[Point]],
edge_curves : Map[Int, Bool],
edge_labels : Map[Int, Box],
) -> EdgeInput {
let route = match routes.get(edge.index) {
Some(ps) => ps
None => edge.route
}
let bend_points = match edge_bend_points.get(edge.index) {
Some(ps) => Some(ps)
None => edge.bend_points
}
let is_curve = edge_curves.get_or_default(edge.index, edge.is_curve)
let label_box = match edge_labels.get(edge.index) {
Some(b) => Some(b)
None => edge.label_box
}
{ ..edge, route, bend_points, is_curve, label_box }
}
///|
pub fn apply_layout(graph : GraphInput, patch : LayoutPatch) -> GraphInput {
let root = apply_box_to_object(graph.root, patch.nodes, patch.node_labels)
let objects : Array[ObjectInput] = []
for obj in graph.objects {
objects.push(apply_box_to_object(obj, patch.nodes, patch.node_labels))
}
let edges : Array[EdgeInput] = []
for e in graph.edges {
edges.push(
apply_route_to_edge(
e,
patch.edges,
patch.edge_bend_points,
patch.edge_curves,
patch.edge_labels,
),
)
}
{
..graph,
root,
objects,
edges,
activation_boxes: patch.activation_boxes,
sequence_notes: patch.sequence_notes,
sequence_fragments_layout: patch.sequence_fragments,
}
}