shuyi_ui/widgets/ask/
glyph.rs1use super::view::AskView;
10use crate::frame::color::{EngineColor, Palette};
11use crate::frame::glyph_buffer::{BoxStyle, Cell, GlyphBuffer, Rect};
12use crate::prelude::*;
13use shuyi_assets::font::CellWidths;
14use shuyi_assets::lang::text_width;
15
16pub const HEIGHT: i32 = 6;
19const ANSWER_GAP: usize = 3;
21
22fn answers_line<T>(view: &AskView<T>, widths: &CellWidths) -> (String, Vec<usize>) {
26 let mut line = String::new();
27 let mut starts = Vec::new();
28 for (i, answer) in view.answers.iter().enumerate() {
29 if i > 0 {
30 line.push_str(&" ".repeat(ANSWER_GAP));
31 }
32 starts.push(text_width(&line, widths));
33 line.push(' ');
34 line.push_str(&answer.label);
35 line.push(' ');
36 }
37 (line, starts)
38}
39
40pub fn rect<T>(view: &AskView<T>, buf: &GlyphBuffer) -> Rect {
43 let widths = buf.widths();
44 let under = match &view.keys {
45 Some(keys) => text_width(keys, widths),
46 None => text_width(&answers_line(view, widths).0, widths),
47 };
48 let widest = text_width(&view.text, widths).max(under);
49 let w = i32::try_from(widest).unwrap_or(0) + 4;
50 Rect::new(
51 (i32::from(buf.width()) - w) / 2,
52 (i32::from(buf.height()) - HEIGHT) / 2,
53 w,
54 HEIGHT,
55 )
56}
57
58pub fn paint<T>(palette: &Palette, view: &AskView<T>, buf: &mut GlyphBuffer) {
60 let c = |e| palette.engine(e);
61 let (bg, text) = (c(EngineColor::Panel), c(EngineColor::Text));
62 let rect = rect(view, buf);
63 buf.fill_rect(rect, Cell::new(' ', text, bg));
64 buf.draw_box(rect, BoxStyle::Double, c(EngineColor::Focus), bg);
65 let (x, y) = (rect.x + 2, rect.y + 2);
66 buf.print(x, y, &view.text, text, bg);
67 if let Some(keys) = &view.keys {
68 buf.print(x, y + 1, keys, c(EngineColor::TextDim), bg);
69 return;
70 }
71 let bar = c(EngineColor::Focus);
72 let (_, starts) = answers_line(view, buf.widths());
73 for (answer, start) in view.answers.iter().zip(starts) {
74 let x = x + i32::try_from(start).unwrap_or(0);
75 let shown = format!(" {} ", answer.label);
76 if answer.focused {
77 buf.print(x, y + 1, &shown, bg, bar);
78 } else {
79 buf.print(x, y + 1, &shown, text, bg);
80 }
81 }
82}