use std::cell::RefCell;
use std::rc::Rc;
use teksilo_canvas::{Rect, SizeProposal};
use teksilo_core::accessibility::AccessNodeBuilder;
use teksilo_core::build_context::BuildContext;
use teksilo_core::widget::{LayoutContext, LayoutResponse, Widget, WidgetPlacement};
use teksilo_core::widget_id::WidgetId;
use teksilo_i18n::LocalizedString;
pub(crate) struct StepPane {
title: LocalizedString,
pending_child: Option<Box<dyn Widget>>,
child_id: Option<WidgetId>,
self_id: Option<WidgetId>,
panel_ids: Rc<RefCell<Vec<WidgetId>>>,
indicator_ids: Rc<RefCell<Vec<WidgetId>>>,
}
impl StepPane {
pub(crate) fn new(
title: LocalizedString,
child: Box<dyn Widget>,
panel_ids: Rc<RefCell<Vec<WidgetId>>>,
indicator_ids: Rc<RefCell<Vec<WidgetId>>>,
) -> Self {
Self {
title,
pending_child: Some(child),
child_id: None,
self_id: None,
panel_ids,
indicator_ids,
}
}
}
impl std::fmt::Debug for StepPane {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("StepPane")
.field("title", &self.title)
.finish()
}
}
impl Widget for StepPane {
fn build(&mut self, ctx: &mut BuildContext) -> Vec<WidgetId> {
self.self_id = Some(ctx.self_id());
if let Some(child) = self.pending_child.take() {
self.child_id = Some(ctx.add_boxed(child));
}
self.child_id.into_iter().collect()
}
fn layout_response(&self, proposal: SizeProposal, ctx: &LayoutContext) -> LayoutResponse {
self.child_id
.and_then(|id| ctx.child_size(id, proposal))
.unwrap_or_else(|| proposal.resolve(0.0, 0.0))
.into()
}
fn place_children(
&self,
bounds: Rect,
_proposal: SizeProposal,
children: &mut [WidgetPlacement],
_ctx: &LayoutContext,
) {
for child in children.iter_mut() {
child.origin = bounds.origin();
child.size = bounds.size();
}
}
fn accessibility(&self, builder: &mut AccessNodeBuilder) {
builder.set_role(teksilo_core::accesskit::Role::TabPanel);
builder.set_name(self.title.resolve_now());
if let Some(self_id) = self.self_id {
let panel_ids = self.panel_ids.borrow();
if let Some(pos) = panel_ids.iter().position(|&id| id == self_id) {
if let Some(&ind_id) = self.indicator_ids.borrow().get(pos) {
builder.push_labelled_by(teksilo_core::accessibility::widget_id_to_node_id(
ind_id,
));
}
}
}
}
fn children(&self) -> Vec<WidgetId> {
self.child_id.into_iter().collect()
}
}