diff --git a/examples/editor-libcosmic/src/text_box.rs b/examples/editor-libcosmic/src/text_box.rs index f0d4789..0e87c52 100644 --- a/examples/editor-libcosmic/src/text_box.rs +++ b/examples/editor-libcosmic/src/text_box.rs @@ -116,9 +116,6 @@ where let buffer = self.buffer.lock().unwrap(); - let font_size = buffer.metrics().font_size; - let line_height = buffer.metrics().line_height; - let instant = Instant::now(); if let Some(background_color) = appearance.background_color { @@ -133,93 +130,28 @@ where ); } - let line_x = layout.bounds().x as i32; - let mut line_y = layout.bounds().y as i32 + font_size; - let mut start_line_opt = None; - let mut end_line = TextLineIndex::new(0); - for (line_i, line) in buffer - .layout_lines() - .iter() - .skip(buffer.scroll() as usize) - .take(buffer.lines() as usize) - .enumerate() - { - end_line = line.line_i; - if start_line_opt == None { - start_line_opt = Some(end_line); + let buffer_x = layout.bounds().x; + let buffer_y = layout.bounds().y; + buffer.draw(text_color_u32, |x, y, w, h, color| { + let a = (color >> 24) as u8; + if a > 0 { + let r = (color >> 16) as u8; + let g = (color >> 8) as u8; + let b = color as u8; + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle::new( + Point::new(buffer_x + x as f32, buffer_y + y as f32), + Size::new(w as f32, h as f32) + ), + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }, + Color::from_rgba8(r, g, b, a as f32 / 255.0), + ); } - - if buffer.cursor.line == line_i + buffer.scroll() as usize { - if buffer.cursor.glyph >= line.glyphs.len() { - let x = match line.glyphs.last() { - Some(glyph) => glyph.x + glyph.w, - None => 0.0, - }; - - renderer.fill_quad( - renderer::Quad { - bounds: Rectangle::new( - Point::new(line_x as f32 + x, (line_y - font_size) as f32), - Size::new((font_size / 2) as f32, line_height as f32) - ), - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }, - Color::from_rgba8(0xFF, 0xFF, 0xFF, 0.125), - ); - } else { - let glyph = &line.glyphs[buffer.cursor.glyph]; - renderer.fill_quad( - renderer::Quad { - bounds: Rectangle::new( - Point::new(line_x as f32 + glyph.x, (line_y - font_size) as f32), - Size::new(glyph.w, line_height as f32) - ), - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }, - Color::from_rgba8(0xFF, 0xFF, 0xFF, 0.125), - ); - - let text_line = &buffer.text_lines()[line.line_i.get()]; - log::info!( - "{}, {}: '{}' ('{}'): '{}'", - glyph.start, - glyph.end, - glyph.font.info.family, - glyph.font.info.post_script_name, - &text_line[glyph.start..glyph.end], - ); - } - } - - line.draw(text_color_u32, |x, y, data| { - let a = (data >> 24) as u8; - if a > 0 { - let r = (data >> 16) as u8; - let g = (data >> 8) as u8; - let b = data as u8; - let bounds = Rectangle::new( - Point::new((line_x + x) as f32, (line_y + y) as f32), - Size::new(1.0, 1.0) - ); - let color = Color::from_rgba8(r, g, b, a as f32 / 255.0); - renderer.fill_quad( - renderer::Quad { - bounds, - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }, - color - ); - } - }); - - line_y += line_height; - } + }); /* // Draw scrollbar diff --git a/examples/editor-orbclient/src/main.rs b/examples/editor-orbclient/src/main.rs index 72fd3ce..8292a9e 100644 --- a/examples/editor-orbclient/src/main.rs +++ b/examples/editor-orbclient/src/main.rs @@ -96,71 +96,27 @@ fn main() { let mut mouse_x = -1; let mut mouse_y = -1; let mut mouse_left = false; - let mut rehit = false; loop { let font_size = buffer.metrics().font_size; let line_height = buffer.metrics().line_height; - if rehit { - let instant = Instant::now(); - - let mut new_cursor_opt = None; - - let mut line_y = line_height; - for (line_i, line) in buffer - .layout_lines() - .iter() - .skip(buffer.scroll() as usize) - .enumerate() - { - if line_y >= window.height() as i32 { - break; - } - - if mouse_left - && mouse_y >= line_y - font_size - && mouse_y < line_y - font_size + line_height - { - let new_cursor_line = line_i + buffer.scroll() as usize; - let mut new_cursor_glyph = line.glyphs.len(); - for (glyph_i, glyph) in line.glyphs.iter().enumerate() { - if mouse_x >= line_x + glyph.x as i32 - && mouse_x <= line_x + (glyph.x + glyph.w) as i32 - { - new_cursor_glyph = glyph_i; - } - } - new_cursor_opt = Some(TextCursor::new(new_cursor_line, new_cursor_glyph)); - } - - line_y += line_height; - } - - if let Some(new_cursor) = new_cursor_opt { - if new_cursor != buffer.cursor { - buffer.cursor = new_cursor; - buffer.redraw = true; - } - } - - rehit = false; - - let duration = instant.elapsed(); - log::debug!("rehit: {:?}", duration); - } - if buffer.redraw { let instant = Instant::now(); window.set(bg_color); - let mut line_y = line_height; + buffer.draw(font_color.data, |x, y, w, h, color| { + window.rect(line_x + x, y, w, h, Color { data: color }); + }); + + let mut line_y = font_size; let mut start_line_opt = None; let mut end_line = TextLineIndex::new(0); for (line_i, line) in buffer .layout_lines() .iter() .skip(buffer.scroll() as usize) + .take(buffer.lines() as usize) .enumerate() { if line_y >= window.height() as i32 { @@ -172,45 +128,6 @@ fn main() { start_line_opt = Some(end_line); } - if buffer.cursor.line == line_i + buffer.scroll() as usize { - if buffer.cursor.glyph >= line.glyphs.len() { - let x = match line.glyphs.last() { - Some(glyph) => glyph.x + glyph.w, - None => 0.0, - }; - window.rect( - line_x + x as i32, - line_y - font_size, - (font_size / 2) as u32, - line_height as u32, - Color::rgba(0xFF, 0xFF, 0xFF, 0x20), - ); - } else { - let glyph = &line.glyphs[buffer.cursor.glyph]; - window.rect( - line_x + glyph.x as i32, - line_y - font_size, - glyph.w as u32, - line_height as u32, - Color::rgba(0xFF, 0xFF, 0xFF, 0x20), - ); - - let text_line = &buffer.text_lines()[line.line_i.get()]; - log::info!( - "{}, {}: '{}' ('{}'): '{}'", - glyph.start, - glyph.end, - glyph.font.info.family, - glyph.font.info.post_script_name, - &text_line[glyph.start..glyph.end], - ); - } - } - - line.draw(font_color.data, |x, y, color| { - window.pixel(line_x + x, line_y + y, Color { data: color }); - }); - line_y += line_height; } @@ -286,14 +203,20 @@ fn main() { mouse_x = event.x; mouse_y = event.y; if mouse_left { - rehit = true; + buffer.action(TextAction::Click { + x: mouse_x - line_x, + y: mouse_y + }); } } EventOption::Button(event) => { if event.left != mouse_left { mouse_left = event.left; if mouse_left { - rehit = true; + buffer.action(TextAction::Click { + x: mouse_x - line_x, + y: mouse_y + }); } } } diff --git a/src/buffer.rs b/src/buffer.rs index 68b6047..6acfd2d 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -385,7 +385,7 @@ impl<'a> TextBuffer<'a> { } }, TextAction::Click { x, y } => { - + self.click(x, y); }, TextAction::Scroll(lines) => { self.scroll += lines; @@ -394,4 +394,103 @@ impl<'a> TextBuffer<'a> { } } } + + fn click(&mut self, mouse_x: i32, mouse_y: i32) { + let instant = Instant::now(); + + let font_size = self.metrics.font_size; + let line_height = self.metrics.line_height; + + let mut new_cursor_opt = None; + + let mut line_y = font_size; + for (line_i, line) in self.layout_lines.iter() + .skip(cmp::max(0, self.scroll()) as usize) + .take(cmp::max(0, self.lines()) as usize) + .enumerate() + { + if mouse_y >= line_y - font_size + && mouse_y < line_y - font_size + line_height + { + let new_cursor_line = line_i + self.scroll() as usize; + let mut new_cursor_glyph = line.glyphs.len(); + for (glyph_i, glyph) in line.glyphs.iter().enumerate() { + if mouse_x >= glyph.x as i32 + && mouse_x <= (glyph.x + glyph.w) as i32 + { + new_cursor_glyph = glyph_i; + } + } + new_cursor_opt = Some(TextCursor::new(new_cursor_line, new_cursor_glyph)); + } + + line_y += line_height; + } + + if let Some(new_cursor) = new_cursor_opt { + if new_cursor != self.cursor { + self.cursor = new_cursor; + self.redraw = true; + } + } + + let duration = instant.elapsed(); + log::debug!("click({}, {}): {:?}", mouse_x, mouse_y, duration); + } + + /// Draw the buffer + pub fn draw(&self, color: u32, mut f: F) + where F: FnMut(i32, i32, u32, u32, u32) + { + let font_size = self.metrics.font_size; + let line_height = self.metrics.line_height; + + let mut line_y = font_size; + for (line_i, line) in self.layout_lines.iter() + .skip(cmp::max(0, self.scroll()) as usize) + .take(cmp::max(0, self.lines()) as usize) + .enumerate() + { + if self.cursor.line == line_i + self.scroll() as usize { + if self.cursor.glyph >= line.glyphs.len() { + let x = match line.glyphs.last() { + Some(glyph) => glyph.x + glyph.w, + None => 0.0, + }; + f( + x as i32, + line_y - font_size, + (font_size / 2) as u32, + line_height as u32, + 0x20FFFFFF, + ); + } else { + let glyph = &line.glyphs[self.cursor.glyph]; + f( + glyph.x as i32, + line_y - font_size, + glyph.w as u32, + line_height as u32, + 0x20FFFFFF, + ); + + let text_line = &self.text_lines()[line.line_i.get()]; + log::info!( + "{}, {}: '{}' ('{}'): '{}'", + glyph.start, + glyph.end, + glyph.font.info.family, + glyph.font.info.post_script_name, + &text_line[glyph.start..glyph.end], + ); + } + } + + line.draw(color, |x, y, color| { + f(x, line_y + y, 1, 1, color); + }); + + line_y += line_height; + } + } }