1use llimphi_ui::llimphi_layout::taffy::{
7 prelude::{length, percent, FlexDirection, Size, Style},
8};
9use llimphi_ui::llimphi_raster::peniko::Color;
10use llimphi_ui::llimphi_text::Alignment;
11use llimphi_ui::{App, Handle, Key, KeyEvent, KeyState, NamedKey, View};
12
13#[derive(Clone)]
14enum Msg {
15 Insert(String),
16 Backspace,
17 Clear,
18}
19
20struct Editor;
21
22impl App for Editor {
23 type Model = String;
24 type Msg = Msg;
25
26 fn title() -> &'static str {
27 "llimphi · editor"
28 }
29
30 fn init(_: &Handle<Self::Msg>) -> Self::Model {
31 String::new()
32 }
33
34 fn update(model: Self::Model, msg: Self::Msg, _: &Handle<Self::Msg>) -> Self::Model {
35 match msg {
36 Msg::Insert(s) => {
37 let mut m = model;
38 m.push_str(&s);
39 m
40 }
41 Msg::Backspace => {
42 let mut m = model;
43 m.pop();
44 m
45 }
46 Msg::Clear => String::new(),
47 }
48 }
49
50 fn on_key(_: &Self::Model, e: &KeyEvent) -> Option<Self::Msg> {
51 if e.state != KeyState::Pressed {
52 return None;
53 }
54 if e.modifiers.ctrl {
55 if let Key::Character(c) = &e.key {
56 if c.eq_ignore_ascii_case("l") {
57 return Some(Msg::Clear);
58 }
59 }
60 return None;
61 }
62 match &e.key {
63 Key::Named(NamedKey::Backspace) => Some(Msg::Backspace),
64 Key::Named(NamedKey::Enter) => Some(Msg::Insert("\n".into())),
65 Key::Named(NamedKey::Tab) => Some(Msg::Insert(" ".into())),
66 _ => e.text.clone().map(Msg::Insert),
67 }
68 }
69
70 fn view(model: &Self::Model) -> View<Self::Msg> {
71 let body_text = if model.is_empty() {
72 "tipea algo · ctrl+L limpia · enter salto · backspace borra".to_string()
73 } else {
74 format!("{model}\u{2588}")
76 };
77 let body_color = if model.is_empty() {
78 Color::from_rgba8(110, 130, 150, 255)
79 } else {
80 Color::from_rgba8(220, 230, 240, 255)
81 };
82
83 let body = View::new(Style {
84 size: Size {
85 width: percent(1.0_f32),
86 height: percent(1.0_f32),
87 },
88 flex_grow: 1.0,
89 ..Default::default()
90 })
91 .text_aligned(body_text, 22.0, body_color, Alignment::Start);
92
93 let status = View::new(Style {
94 size: Size {
95 width: percent(1.0_f32),
96 height: length(36.0_f32),
97 },
98 ..Default::default()
99 })
100 .fill(Color::from_rgba8(30, 36, 48, 255))
101 .text(
102 format!("{} chars", model.chars().count()),
103 16.0,
104 Color::from_rgba8(160, 180, 200, 255),
105 );
106
107 View::new(Style {
108 flex_direction: FlexDirection::Column,
109 size: Size {
110 width: percent(1.0_f32),
111 height: percent(1.0_f32),
112 },
113 gap: Size {
114 width: length(0.0_f32),
115 height: length(8.0_f32),
116 },
117 padding: llimphi_ui::llimphi_layout::taffy::Rect {
118 left: length(24.0_f32),
119 right: length(24.0_f32),
120 top: length(24.0_f32),
121 bottom: length(24.0_f32),
122 },
123 ..Default::default()
124 })
125 .fill(Color::from_rgba8(20, 24, 32, 255))
126 .children(vec![body, status])
127 }
128}
129
130fn main() {
131 llimphi_ui::run::<Editor>();
132}