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