blizz_ui/
wizard_composer.rs1use std::io::{self, Write};
8
9use crate::Renderer;
10use crate::components::hint::HintComponent;
11use crate::components::selector::SelectorComponent;
12use crate::components::text::TextComponent;
13use crate::components::text_entry::TextEntryComponent;
14use crate::components::timer_bar::TimerBarComponent;
15use crate::layout_stack::{Align, LayoutStack};
16use crate::prompt;
17
18#[derive(Clone, Copy)]
20pub struct WizardPromptRefs<'a> {
21 pub question: &'a TextComponent,
22 pub entry: &'a TextEntryComponent,
23 pub selector: &'a SelectorComponent,
24 pub hint: &'a HintComponent,
25 pub timer_bar: &'a TimerBarComponent,
26}
27
28#[cfg(not(tarpaulin_include))]
29pub fn render_prompt_layer<W: Write>(
30 renderer: &mut Renderer<W>,
31 refs: WizardPromptRefs<'_>,
32) -> io::Result<()> {
33 let terminal_width = renderer.ctx().terminal_size.width;
34 let layout = match refs.entry.layout() {
35 Some(l) => l,
36 None => return Ok(()),
37 };
38
39 let mut stack = LayoutStack::new(
40 layout.question_row,
41 terminal_width,
42 layout.box_column,
43 layout.inner_width,
44 );
45
46 let question_width = refs.question.text.chars().count() as u16;
47 stack.draw(renderer, refs.question, Align::Content(question_width))?;
48
49 if refs.selector.visible {
50 stack.draw(renderer, refs.selector, Align::Full)?;
51 stack.skip(1);
52 return draw_footer(&mut stack, renderer, refs.hint, refs.timer_bar);
53 }
54
55 if refs.entry.visible && refs.entry.open > 0.0 {
56 stack.draw(renderer, refs.entry, Align::Box)?;
57 } else {
58 let box_height = layout.hint_row.saturating_sub(layout.box_top_row);
59 stack.skip(box_height);
60 }
61
62 draw_footer(&mut stack, renderer, refs.hint, refs.timer_bar)?;
63
64 if refs.entry.is_fully_ready()
65 && let Some(col) = refs.entry.cursor_column(terminal_width)
66 {
67 prompt::queue_cursor(&mut renderer.writer, layout, col)?;
68 }
69
70 Ok(())
71}
72
73#[cfg(not(tarpaulin_include))]
74fn draw_footer<W: Write>(
75 stack: &mut LayoutStack,
76 renderer: &mut Renderer<W>,
77 hint: &HintComponent,
78 timer_bar: &TimerBarComponent,
79) -> io::Result<()> {
80 let hint_width = hint.text.chars().count() as u16;
81 stack.draw(renderer, hint, Align::Content(hint_width))?;
82
83 let seg = TimerBarComponent::segment_count(timer_bar.progress, stack.terminal_width());
84 stack.draw(renderer, timer_bar, Align::Content(seg as u16))?;
85 Ok(())
86}