///|
// Membership follows the source Grouper independently of Figure's panel list.
// Explicit retained handles keep targets alive; Python weak-reference expiry is
// outside this typed Scene profile.
priv struct SharedAxesGroup {
id : Int32
members : Array[@ref.Ref[AxesData]]
}
///|
fn Axes::ensure_shared_registration(
self : Axes,
horizontal : Bool,
) -> SharedAxesGroup {
let existing = if horizontal {
self.state.val.share_x_members
} else {
self.state.val.share_y_members
}
if existing is Some(group) {
return group
}
let group : SharedAxesGroup = {
id: self.figure.allocate_share_group(1),
members: [self.state],
}
if horizontal {
self.state.val.share_x_members = Some(group)
self.state.val.share_x_group = Some(group.id)
self.state.val.share_x_order = self.figure.share_x_next_order
self.figure.share_x_next_order += 1L
} else {
self.state.val.share_y_members = Some(group)
self.state.val.share_y_group = Some(group.id)
self.state.val.share_y_order = self.figure.share_y_next_order
self.figure.share_y_next_order += 1L
}
group
}
///|
fn Axes::join_shared_axis(
self : Axes,
target : @ref.Ref[AxesData],
horizontal : Bool,
) -> Unit {
// Grouper.join registers self before its argument, including fresh re-joins.
let own = self.ensure_shared_registration(horizontal)
let other_axes : Axes = { figure: self.figure, state: target, }
let other = other_axes.ensure_shared_registration(horizontal)
if physical_equal(own, other) {
return
}
let (destination, source) = if own.members.length() < other.members.length() {
(other, own)
} else {
(own, other)
}
for state in source.members {
destination.members.push(state)
}
destination.members.sort_by((left, right) => {
let first = if horizontal {
left.val.share_x_order
} else {
left.val.share_y_order
}
let second = if horizontal {
right.val.share_x_order
} else {
right.val.share_y_order
}
first.compare(second)
})
for state in destination.members {
if horizontal {
state.val.share_x_members = Some(destination)
state.val.share_x_group = Some(destination.id)
} else {
state.val.share_y_members = Some(destination)
state.val.share_y_group = Some(destination.id)
}
}
}
///|
fn Axes::unregister_shared_axis(
self : Axes,
horizontal : Bool,
) -> Array[@ref.Ref[AxesData]] {
let existing = if horizontal {
self.state.val.share_x_members
} else {
self.state.val.share_y_members
}
let remaining = match existing {
Some(group) => {
group.members.retain(state => !physical_equal(state, self.state))
group.members.copy()
}
None => []
}
if horizontal {
self.state.val.share_x_members = None
self.state.val.share_x_group = None
} else {
self.state.val.share_y_members = None
self.state.val.share_y_group = None
}
remaining
}