use crate::env::{Env, RuntimeState};
use crate::lowering::{LoweringContext};
use crate::ui::traits::Lower;
use crate::ui::Node;
use crate::hit_test::find_next_focus_node;
use fission_core::{ActionEnvelope, ActionId, Op};
use fission_ir::{CoreIR, NodeId, Semantics, semantics::Role};
#[test]
fn test_explicit_focus_order() {
let env = Env::default();
let runtime_state = RuntimeState::default();
fn button_with_focus(index: i32) -> Node {
Node::Custom(fission_core::ui::CustomNode {
debug_tag: format!("Button({})", index),
lowerer: Some(std::sync::Arc::new(FocusButtonLowerer { index })),
})
}
#[derive(Debug)]
struct FocusButtonLowerer { index: i32 }
impl fission_core::LowerDyn for FocusButtonLowerer {
fn lower_dyn(&self, cx: &mut fission_core::LoweringContext) -> fission_ir::NodeId {
let id = cx.next_node_id();
let s = Semantics {
role: Role::Button,
focusable: true,
focus_index: Some(self.index), capture_tab: false, auto_indent: false,
..Default::default()
};
fission_core::NodeBuilder::new(id, Op::Semantics(s)).build(cx)
}
fn stable_key(&self) -> u64 { self.index as u64 }
}
let root = crate::ui::widgets::column::Column {
children: vec![button_with_focus(2), button_with_focus(1), button_with_focus(3)],
..Default::default()
};
let mut cx = LoweringContext::new(&env, &runtime_state, None, None);
let root_id = root.lower(&mut cx);
cx.ir.root = Some(root_id);
let mut b_index1_id = None;
let mut b_index2_id = None;
let mut b_index3_id = None;
for (id, node) in &cx.ir.nodes {
if let Op::Semantics(s) = &node.op {
match s.focus_index {
Some(1) => b_index1_id = Some(*id),
Some(2) => b_index2_id = Some(*id),
Some(3) => b_index3_id = Some(*id),
_ => {}
}
}
}
let b_index1_id = b_index1_id.expect("B(1) not found");
let b_index2_id = b_index2_id.expect("B(2) not found");
let b_index3_id = b_index3_id.expect("B(3) not found");
let all_nodes = crate::hit_test::get_all_focusable_nodes(&cx.ir);
println!("DEBUG: all_focusable_nodes: {:?}", all_nodes);
println!("DEBUG: B(1): {:?}, B(2): {:?}, B(3): {:?}", b_index1_id, b_index2_id, b_index3_id);
let next = find_next_focus_node(&cx.ir, Some(b_index1_id), false);
assert_eq!(next, Some(b_index2_id), "Tab from B(1) should go to B(2)");
let next = find_next_focus_node(&cx.ir, Some(b_index2_id), false);
assert_eq!(next, Some(b_index3_id), "Tab from B(2) should go to B(3)");
let next = find_next_focus_node(&cx.ir, Some(b_index3_id), false);
assert_eq!(next, Some(b_index1_id), "Tab from B(3) should cycle to B(1)");
}