From b253800383d449554c9422cec670f65a04711651 Mon Sep 17 00:00:00 2001 From: Hojjat Date: Thu, 10 Nov 2022 11:55:12 -0700 Subject: [PATCH] Add Padding to the TextBox (#36) * WIP: initial text-margin support * Fix the selection issue when clicking the margins * Move the margin size into the main * using padding, consistent with iced text_input * Added top and bottom margin * bugfix: selection starting from the top margin works * bugfix: left half of first glyph was being ignored --- .../editor-libcosmic/src/syntax_text_box.rs | 24 +++++++++++------ examples/editor-libcosmic/src/text_box.rs | 27 ++++++++++++------- src/buffer.rs | 19 +++++++++++-- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/examples/editor-libcosmic/src/syntax_text_box.rs b/examples/editor-libcosmic/src/syntax_text_box.rs index 2b290bb..57abbb5 100644 --- a/examples/editor-libcosmic/src/syntax_text_box.rs +++ b/examples/editor-libcosmic/src/syntax_text_box.rs @@ -11,6 +11,7 @@ use cosmic::{ mouse::{self, Button, Event as MouseEvent, ScrollDelta}, renderer, widget::{self, tree, Widget}, + Padding }, }; use cosmic_text::{ @@ -27,14 +28,21 @@ use super::text; pub struct SyntaxTextBox<'a> { editor: &'a Mutex>, + padding: Padding, } impl<'a> SyntaxTextBox<'a> { pub fn new(editor: &'a Mutex>) -> Self { Self { editor, + padding: Padding::new(0), } } + + pub fn padding>(mut self, padding: P) -> Self { + self.padding = padding.into(); + self + } } pub fn syntax_text_box<'a>(editor: &'a Mutex>) -> SyntaxTextBox<'a> { @@ -116,8 +124,8 @@ where let mut editor = self.editor.lock().unwrap(); - let view_w = cmp::min(viewport.width as i32, layout.bounds().width as i32); - let view_h = cmp::min(viewport.height as i32, layout.bounds().height as i32); + let view_w = cmp::min(viewport.width as i32, layout.bounds().width as i32) - self.padding.horizontal() as i32; + let view_h = cmp::min(viewport.height as i32, layout.bounds().height as i32)- self.padding.vertical() as i32; editor.buffer_mut().set_size(view_w, view_h); editor.shape_as_needed(); @@ -137,7 +145,7 @@ where renderer.fill_quad( renderer::Quad { bounds: Rectangle::new( - Point::new(layout.position().x + x as f32, layout.position().y + y as f32), + layout.position() + [x as f32, y as f32].into() + [self.padding.left as f32, self.padding.top as f32].into(), Size::new(w as f32, h as f32) ), border_radius: 0.0, @@ -158,7 +166,7 @@ where let handle = image::Handle::from_pixels(view_w as u32, view_h as u32, pixels); image::Renderer::draw(renderer, handle, Rectangle::new( - layout.position(), + layout.position() + [self.padding.left as f32, self.padding.top as f32].into(), Size::new(view_w as f32, view_h as f32) )); @@ -235,8 +243,8 @@ where Event::Mouse(MouseEvent::ButtonPressed(Button::Left)) => { if layout.bounds().contains(cursor_position) { editor.action(Action::Click { - x: (cursor_position.x - layout.bounds().x) as i32, - y: (cursor_position.y - layout.bounds().y) as i32, + x: (cursor_position.x - layout.bounds().x) as i32 - self.padding.left as i32, + y: (cursor_position.y - layout.bounds().y) as i32 - self.padding.top as i32, }); state.is_dragging = true; status = Status::Captured; @@ -249,8 +257,8 @@ where Event::Mouse(MouseEvent::CursorMoved { .. }) => { if state.is_dragging { editor.action(Action::Drag { - x: (cursor_position.x - layout.bounds().x) as i32, - y: (cursor_position.y - layout.bounds().y) as i32, + x: (cursor_position.x - layout.bounds().x) as i32 - self.padding.left as i32, + y: (cursor_position.y - layout.bounds().y) as i32 - self.padding.top as i32, }); status = Status::Captured; } diff --git a/examples/editor-libcosmic/src/text_box.rs b/examples/editor-libcosmic/src/text_box.rs index f4435dd..768daa2 100644 --- a/examples/editor-libcosmic/src/text_box.rs +++ b/examples/editor-libcosmic/src/text_box.rs @@ -11,6 +11,7 @@ use cosmic::{ mouse::{self, Button, Event as MouseEvent, ScrollDelta}, renderer, widget::{self, tree, Widget}, + Padding }, theme::Theme, }; @@ -52,14 +53,22 @@ impl StyleSheet for Theme { pub struct TextBox<'a> { editor: &'a Mutex>, + padding: Padding, } impl<'a> TextBox<'a> { pub fn new(editor: &'a Mutex>) -> Self { Self { editor, + padding: Padding::new(0), } } + + pub fn padding>(mut self, padding: P) -> Self { + self.padding = padding.into(); + self + } + } pub fn text_box<'a>(editor: &'a Mutex>) -> TextBox<'a> { @@ -163,8 +172,8 @@ where let mut editor = self.editor.lock().unwrap(); - let view_w = cmp::min(viewport.width as i32, layout.bounds().width as i32); - let view_h = cmp::min(viewport.height as i32, layout.bounds().height as i32); + let view_w = cmp::min(viewport.width as i32, layout.bounds().width as i32) - self.padding.horizontal() as i32; + let view_h = cmp::min(viewport.height as i32, layout.bounds().height as i32) - self.padding.vertical() as i32; editor.buffer.set_size(view_w, view_h); editor.shape_as_needed(); @@ -184,8 +193,8 @@ where renderer.fill_quad( renderer::Quad { bounds: Rectangle::new( - Point::new(layout.position().x + x as f32, layout.position().y + y as f32), - Size::new(w as f32, h as f32) + layout.position() + [x as f32, y as f32].into() + [self.padding.left as f32, self.padding.top as f32].into(), + Size::new(w as f32 , h as f32) ), border_radius: 0.0, border_width: 0.0, @@ -205,7 +214,7 @@ where let handle = image::Handle::from_pixels(view_w as u32, view_h as u32, pixels); image::Renderer::draw(renderer, handle, Rectangle::new( - layout.position(), + layout.position() + [self.padding.left as f32, self.padding.top as f32].into(), Size::new(view_w as f32, view_h as f32) )); @@ -282,8 +291,8 @@ where Event::Mouse(MouseEvent::ButtonPressed(Button::Left)) => { if layout.bounds().contains(cursor_position) { editor.action(Action::Click { - x: (cursor_position.x - layout.bounds().x) as i32, - y: (cursor_position.y - layout.bounds().y) as i32, + x: (cursor_position.x - layout.bounds().x) as i32 - self.padding.left as i32, + y: (cursor_position.y - layout.bounds().y) as i32 - self.padding.top as i32, }); state.is_dragging = true; status = Status::Captured; @@ -296,8 +305,8 @@ where Event::Mouse(MouseEvent::CursorMoved { .. }) => { if state.is_dragging { editor.action(Action::Drag { - x: (cursor_position.x - layout.bounds().x) as i32, - y: (cursor_position.y - layout.bounds().y) as i32, + x: (cursor_position.x - layout.bounds().x) as i32 - self.padding.left as i32, + y: (cursor_position.y - layout.bounds().y) as i32 - self.padding.top as i32, }); status = Status::Captured; } diff --git a/src/buffer.rs b/src/buffer.rs index 12f33b4..2018cf5 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -424,15 +424,30 @@ impl<'a> Buffer<'a> { let mut new_cursor_opt = None; let mut runs = self.layout_runs().peekable(); + let mut first_run = true; while let Some(run) = runs.next() { let line_y = run.line_y; - if y >= line_y - font_size - && y < line_y - font_size + line_height + if first_run && y < line_y - font_size { + first_run = false; + let new_cursor = Cursor::new(run.line_i, 0); + new_cursor_opt = Some(new_cursor); + } else if y >= line_y - font_size + && y < line_y - font_size + line_height { let mut new_cursor_glyph = run.glyphs.len(); let mut new_cursor_char = 0; + + let mut first_glyph = true; + 'hit: for (glyph_i, glyph) in run.glyphs.iter().enumerate() { + if first_glyph { + first_glyph = false; + if (run.rtl && x > glyph.x as i32) || (!run.rtl && x < 0) { + new_cursor_glyph = 0; + new_cursor_char = 0; + } + } if x >= glyph.x as i32 && x <= (glyph.x + glyph.w) as i32 {