Skip to main content

winio_ui_gtk/ui/
text_box.rs

1use 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);