makepad_widget/
textinput.rs

1use makepad_render::*;
2use crate::texteditor::*;
3use crate::textbuffer::*;
4use crate::plaineditor::*;
5use crate::widgetstyle::*;
6#[derive(Clone)]
7pub struct TextInput {
8    pub text_editor: TextEditor,
9    pub text_buffer: TextBuffer,
10    pub empty_message: String,
11}
12
13pub struct TextInputOptions {
14    pub multiline: bool,
15    pub read_only: bool,
16    pub empty_message: String
17}
18
19impl TextInput {
20    
21    pub fn proto(cx: &mut Cx, opt: TextInputOptions) -> Self {
22        Self {
23            text_editor: TextEditor {
24                read_only: opt.read_only,
25                multiline: opt.multiline,
26                draw_line_numbers: false,
27                draw_cursor_row: false,
28                highlight_area_on: false,
29                line_number_width: 0.,
30                top_padding: 0.,
31                mark_unmatched_parens: false,
32                view_layout: Layout {
33                    walk: Walk {width: Width::Compute, height: Height::Compute, margin: Margin {t: 4., l: 0., r: 0., b: 0.}},
34                    padding: Padding::all(7.),
35                    ..Layout::default()
36                },
37                folding_depth: 3,
38                ..TextEditor::proto(cx)
39            },
40            empty_message: opt.empty_message,
41            text_buffer: TextBuffer::from_utf8(""),
42        }
43    }
44    
45    pub fn style_text_input() -> StyleId {uid!()}
46    
47    pub fn style(cx: &mut Cx, _opt: &StyleOptions) {
48        cx.begin_style(Self::style_text_input());
49        TextEditor::color_bg().set(cx, Theme::color_bg_normal().get(cx));
50        TextEditor::gutter_width().set(cx, 0.);
51        TextEditor::padding_top().set(cx, 0.);
52        TextEditor::shader_bg().set(cx, Quad::def_quad_shader().compose(shader_ast!({
53            fn pixel() -> vec4 {
54                df_viewport(pos * vec2(w, h));
55                df_box(0., 0., w, h, 2.5);
56                return df_fill(color);
57            }
58        })));
59        cx.end_style();
60    }
61    
62    pub fn handle_text_input(&mut self, cx: &mut Cx, event: &mut Event) -> TextEditorEvent {
63        let text_buffer = &mut self.text_buffer;
64        let ce = self.text_editor.handle_text_editor(cx, event, text_buffer);
65        ce
66    }
67    
68    pub fn set_value(&mut self, cx: &mut Cx, text: &str) {
69        let text_buffer = &mut self.text_buffer;
70        text_buffer.load_from_utf8(text);
71        self.text_editor.view.redraw_view_area(cx);
72    }
73    
74    pub fn get_value(&self) -> String {
75        self.text_buffer.get_as_string()
76    }
77    
78    pub fn draw_text_input_static(&mut self, cx: &mut Cx, text: &str) {
79        let text_buffer = &mut self.text_buffer;
80        text_buffer.load_from_utf8(text);
81        self.draw_text_input(cx);
82    }
83    
84    pub fn draw_text_input(&mut self, cx: &mut Cx) {
85        cx.begin_style(Self::style_text_input());
86        let text_buffer = &mut self.text_buffer;
87        if text_buffer.needs_token_chunks() && text_buffer.lines.len() >0 {
88            
89            let mut state = TokenizerState::new(&text_buffer.lines);
90            let mut tokenizer = PlainTokenizer::new();
91            let mut pair_stack = Vec::new();
92            loop {
93                let offset = text_buffer.flat_text.len();
94                let token_type = tokenizer.next_token(&mut state, &mut text_buffer.flat_text, &text_buffer.token_chunks);
95                TokenChunk::push_with_pairing(&mut text_buffer.token_chunks, &mut pair_stack, state.next, offset, text_buffer.flat_text.len(), token_type);
96                if token_type == TokenType::Eof {
97                    break
98                }
99            }
100        }
101        
102        if self.text_editor.begin_text_editor(cx, text_buffer).is_err() {return cx.end_style();}
103        
104        if text_buffer.is_empty() {
105            let pos = cx.get_turtle_pos();
106            self.text_editor.text.color = color("#666");
107            self.text_editor.text.draw_text(cx, &self.empty_message);
108            cx.set_turtle_pos(pos);
109        }
110        
111        for (index, token_chunk) in text_buffer.token_chunks.iter_mut().enumerate() {
112            self.text_editor.draw_chunk(cx, index, &text_buffer.flat_text, token_chunk, &text_buffer.messages.cursors);
113        }
114        
115        self.text_editor.end_text_editor(cx, text_buffer);
116        cx.end_style();
117    }
118}