use rdom_core::{NodeId, NodeType};
use crate::TuiDom;
use crate::layout::UserSelect;
use crate::node::TuiNodeExt;
fn own_used_value(dom: &TuiDom, id: NodeId) -> Option<UserSelect> {
let node = dom.node(id);
match node.computed()?.user_select {
UserSelect::Auto if node.is_editable() => Some(UserSelect::Contain),
UserSelect::Auto => None,
v => Some(v),
}
}
fn from_parent(parent: UserSelect) -> UserSelect {
match parent {
UserSelect::All | UserSelect::None => parent,
_ => UserSelect::Text,
}
}
pub(crate) fn resolve_child(dom: &TuiDom, id: NodeId, parent: UserSelect) -> UserSelect {
own_used_value(dom, id).unwrap_or_else(|| from_parent(parent))
}
pub(crate) fn used_value(dom: &TuiDom, id: NodeId) -> UserSelect {
let mut is_self = true;
let mut cur = Some(id);
while let Some(n) = cur {
if let Some(v) = own_used_value(dom, n) {
return if is_self { v } else { from_parent(v) };
}
if dom.node(n).node_type() == NodeType::Element {
is_self = false;
}
cur = dom.node(n).parent_node().map(|p| p.id());
}
UserSelect::Text
}
pub(crate) fn is_unselectable(dom: &TuiDom, id: NodeId) -> bool {
used_value(dom, id) == UserSelect::None
}
pub(crate) fn all_host(dom: &TuiDom, id: NodeId) -> Option<NodeId> {
let mut host = None;
let mut cur = Some(id);
while let Some(n) = cur {
if own_used_value(dom, n) == Some(UserSelect::All) {
host = Some(n);
}
cur = dom.node(n).parent_node().map(|p| p.id());
}
host
}
pub(crate) fn contain_host(dom: &TuiDom, id: NodeId) -> Option<NodeId> {
let mut cur = Some(id);
while let Some(n) = cur {
if own_used_value(dom, n) == Some(UserSelect::Contain) {
return Some(n);
}
cur = dom.node(n).parent_node().map(|p| p.id());
}
None
}
#[cfg(test)]
mod tests;