winio_ui_gtk/ui/
text_box.rs1use std::rc::Rc;
2
3use gtk4::{
4 Justification, WrapMode,
5 glib::object::Cast,
6 prelude::{TextBufferExt, TextViewExt},
7};
8use inherit_methods_macro::inherit_methods;
9use winio_callback::Callback;
10use winio_handle::AsContainer;
11use winio_primitive::{HAlign, Point, Size};
12
13use crate::{GlobalRuntime, Result, ui::Widget};
14
15#[derive(Debug)]
16pub struct TextBox {
17 on_changed: Rc<Callback<()>>,
18 widget: gtk4::TextView,
19 handle: Widget,
20}
21
22#[inherit_methods(from = "self.handle")]
23impl TextBox {
24 pub fn new(parent: impl AsContainer) -> Result<Self> {
25 let container = gtk4::ScrolledWindow::new();
26 let widget = gtk4::TextView::new();
27 container.set_child(Some(&widget));
28
29 widget.set_wrap_mode(WrapMode::Char);
30 let handle = Widget::new(parent, unsafe { container.clone().unsafe_cast() })?;
31
32 let buffer = widget.buffer();
33 let on_changed = Rc::new(Callback::new());
34 buffer.connect_changed({
35 let on_changed = on_changed.clone();
36 move |_| {
37 on_changed.signal::<GlobalRuntime>(());
38 }
39 });
40 Ok(Self {
41 on_changed,
42 widget,
43 handle,
44 })
45 }
46
47 pub fn is_visible(&self) -> Result<bool>;
48
49 pub fn set_visible(&mut self, v: bool) -> Result<()>;
50
51 pub fn is_enabled(&self) -> Result<bool>;
52
53 pub fn set_enabled(&mut self, v: bool) -> Result<()>;
54
55 pub fn preferred_size(&self) -> Result<Size>;
56
57 pub fn min_size(&self) -> Result<Size> {
58 let size = self.preferred_size()?;
59 Ok(Size::new(size.width, 0.0))
60 }
61
62 pub fn loc(&self) -> Result<Point>;
63
64 pub fn set_loc(&mut self, p: Point) -> Result<()>;
65
66 pub fn size(&self) -> Result<Size>;
67
68 pub fn set_size(&mut self, s: Size) -> Result<()>;
69
70 pub fn tooltip(&self) -> Result<String>;
71
72 pub fn set_tooltip(&mut self, s: impl AsRef<str>) -> Result<()>;
73
74 pub fn text(&self) -> Result<String> {
75 let buffer = self.widget.buffer();
76 Ok(buffer
77 .text(&buffer.start_iter(), &buffer.end_iter(), true)
78 .to_string())
79 }
80
81 pub fn set_text(&mut self, s: impl AsRef<str>) -> Result<()> {
82 self.widget.buffer().set_text(s.as_ref());
83 self.handle.reset_preferred_size();
84 Ok(())
85 }
86
87 pub fn halign(&self) -> Result<HAlign> {
88 let align = self.widget.justification();
89 let align = match align {
90 Justification::Center => HAlign::Center,
91 Justification::Right => HAlign::Right,
92 Justification::Fill => HAlign::Stretch,
93 _ => HAlign::Left,
94 };
95 Ok(align)
96 }
97
98 pub fn set_halign(&mut self, align: HAlign) -> Result<()> {
99 let align = match align {
100 HAlign::Left => Justification::Left,
101 HAlign::Center => Justification::Center,
102 HAlign::Right => Justification::Right,
103 HAlign::Stretch => Justification::Fill,
104 };
105 self.widget.set_justification(align);
106 Ok(())
107 }
108
109 pub fn is_readonly(&self) -> Result<bool> {
110 Ok(!self.widget.is_editable())
111 }
112
113 pub fn set_readonly(&mut self, r: bool) -> Result<()> {
114 self.widget.set_editable(!r);
115 Ok(())
116 }
117
118 pub async fn wait_change(&self) {
119 self.on_changed.wait().await
120 }
121}
122
123winio_handle::impl_as_widget!(TextBox, handle);