From b092ef65e9099668a543b32f978a9e09201e4074 Mon Sep 17 00:00:00 2001 From: Adrian Wozniak Date: Fri, 4 Jan 2019 10:40:29 +0100 Subject: [PATCH] Add text --- src/app/app_state.rs | 88 ++++++- src/app/keyboard_handler.rs | 281 +++++++++++++++++++++++ src/app/mod.rs | 32 ++- src/main.rs | 1 - src/ui/caret.rs | 44 +++- src/{ => ui}/file/editor_file.rs | 30 ++- src/{ => ui}/file/editor_file_section.rs | 15 +- src/{ => ui}/file/editor_file_token.rs | 19 +- src/{ => ui}/file/mod.rs | 0 src/ui/mod.rs | 21 +- src/ui/text_character.rs | 27 ++- 11 files changed, 519 insertions(+), 39 deletions(-) create mode 100644 src/app/keyboard_handler.rs rename src/{ => ui}/file/editor_file.rs (76%) rename src/{ => ui}/file/editor_file_section.rs (85%) rename src/{ => ui}/file/editor_file_token.rs (86%) rename src/{ => ui}/file/mod.rs (100%) diff --git a/src/app/app_state.rs b/src/app/app_state.rs index f9e7144..de3b62d 100644 --- a/src/app/app_state.rs +++ b/src/app/app_state.rs @@ -1,7 +1,7 @@ use crate::app::{UpdateResult, WindowCanvas}; use crate::config::Config; -use crate::file::*; -use crate::file::editor_file::EditorFile; +use crate::ui::file::*; +use crate::ui::file::editor_file::EditorFile; use crate::renderer::Renderer; use crate::ui::*; use crate::ui::caret::Caret; @@ -10,6 +10,7 @@ use sdl2::rect::Point; use std::boxed::Box; use std::rc::Rc; use std::sync::Arc; +use sdl2::rect::Rect; pub struct AppState { menu_bar: MenuBar, @@ -40,6 +41,85 @@ impl AppState { pub fn caret(&mut self) -> &mut Caret { &mut self.caret } + + pub fn delete_front(&mut self, config: &Config) { + let file: &mut EditorFile = if let Some(file) = self.files.get_mut(self.current_file) { + file + } else { + return; + }; + let mut buffer: String = file.buffer(); + let caret: &mut Caret = &mut self.caret; + let position: usize = caret.text_position(); + if position == 0 { + return; + } + buffer.remove(position); + match file.get_character_at(position - 1) { + Some(character) => { + let dest: &Rect = character.dest(); + caret.move_caret(position - 1, Point::new( + dest.x(), dest.y(), + )); + } + _ => { + caret.reset_caret(); + } + } + let new_file = EditorFile::new( + file.path(), + buffer, + config, + ); + self.files[self.current_file] = new_file; + } + + pub fn delete_back(&mut self, config: &Config) { + let file: &mut EditorFile = if let Some(file) = self.files.get_mut(self.current_file) { + file + } else { + return; + }; + let mut buffer: String = file.buffer(); + let caret: &mut Caret = &mut self.caret; + let position: usize = caret.text_position(); + if position >= buffer.len() { + return; + } + buffer.remove(position); + let new_file = EditorFile::new( + file.path(), + buffer, + config, + ); + self.files[self.current_file] = new_file; + } + + pub fn insert_character(&mut self, character: char, renderer: &mut Renderer) { + let file: &mut EditorFile = if let Some(file) = self.files.get_mut(self.current_file) { + file + } else { + return; + }; + let mut buffer: String = file.buffer(); + let caret: &mut Caret = &mut self.caret; + let position: usize = caret.text_position(); + buffer.insert(position, character.clone()); + let new_file = EditorFile::new( + file.path(), + buffer, + renderer.config(), + ); + if let Some(rect) = get_text_character_rect(character, renderer) { + if let Some(current) = file.get_character_at(position) { + caret.move_caret(position + 1, Point::new( + current.dest().x() + rect.width() as i32, + current.dest().y(), + )); + } + } + self.files[self.current_file] = new_file; + } } impl Render for AppState { @@ -72,8 +152,8 @@ impl ClickHandler for AppState { if let Some(current_file) = self.files.get_mut(self.current_file) { if current_file.is_left_click_target(point) { match current_file.on_left_click(point, config) { - UpdateResult::MoveCaret(rect) => { - self.caret.move_caret(Point::new(rect.x(), rect.y())); + UpdateResult::MoveCaret(rect, position) => { + self.caret.move_caret(position, Point::new(rect.x(), rect.y())); } _ => (), }; diff --git a/src/app/keyboard_handler.rs b/src/app/keyboard_handler.rs new file mode 100644 index 0000000..0c50272 --- /dev/null +++ b/src/app/keyboard_handler.rs @@ -0,0 +1,281 @@ +use sdl2::keyboard::{Keycode, Scancode}; +use sdl2::event::EventPollIterator; +use sdl2::EventPump; + +use crate::app::UpdateResult; + +pub fn resolve_action(key_code: Keycode, event_pump: &mut EventPump) -> UpdateResult { + match key_code { + Keycode::Backspace => return UpdateResult::DeleteFront, + Keycode::Delete => return UpdateResult::DeleteBack, + + Keycode::Escape => return UpdateResult::NoOp, + + Keycode::Space => { + let character: char = ' '; + return UpdateResult::Input(character); + } + Keycode::Exclaim => { + let character: char = '!'; + return UpdateResult::Input(character); + } + Keycode::Quotedbl => { + let character: char = '"'; + return UpdateResult::Input(character); + } + Keycode::Hash => { + let character: char = '#'; + return UpdateResult::Input(character); + } + Keycode::Dollar => { + let character: char = '$'; + return UpdateResult::Input(character); + } + Keycode::Percent => { + let character: char = '%'; + return UpdateResult::Input(character); + } + Keycode::Ampersand => { + let character: char = '&'; + return UpdateResult::Input(character); + } + Keycode::Quote => { + let character: char = '\''; + return UpdateResult::Input(character); + } + Keycode::LeftParen => { + let character: char = '{'; + return UpdateResult::Input(character); + } + Keycode::RightParen => { + let character: char = '}'; + return UpdateResult::Input(character); + } + Keycode::Asterisk => { + let character: char = '*'; + return UpdateResult::Input(character); + } + Keycode::Plus => { + let character: char = '+'; + return UpdateResult::Input(character); + } + Keycode::Comma => { + let character: char = ','; + return UpdateResult::Input(character); + } + Keycode::Minus => { + let character: char = '-'; + return UpdateResult::Input(character); + } + Keycode::Period => { + let character: char = '.'; + return UpdateResult::Input(character); + } + Keycode::Slash => { + let character: char = '/'; + return UpdateResult::Input(character); + } + Keycode::Num0 => { + let character: char = '0'; + return UpdateResult::Input(character); + } + Keycode::Num1 => { + let character: char = '1'; + return UpdateResult::Input(character); + } + Keycode::Num2 => { + let character: char = '2'; + return UpdateResult::Input(character); + } + Keycode::Num3 => { + let character: char = '3'; + return UpdateResult::Input(character); + } + Keycode::Num4 => { + let character: char = '4'; + return UpdateResult::Input(character); + } + Keycode::Num5 => { + let character: char = '5'; + return UpdateResult::Input(character); + } + Keycode::Num6 => { + let character: char = '6'; + return UpdateResult::Input(character); + } + Keycode::Num7 => { + let character: char = '7'; + return UpdateResult::Input(character); + } + Keycode::Num8 => { + let character: char = '8'; + return UpdateResult::Input(character); + } + Keycode::Num9 => { + let character: char = '9'; + return UpdateResult::Input(character); + } + Keycode::Colon => { + let character: char = ':'; + return UpdateResult::Input(character); + } + Keycode::Semicolon => { + let character: char = ';'; + return UpdateResult::Input(character); + } + Keycode::Less => { + let character: char = '<'; + return UpdateResult::Input(character); + } + Keycode::Equals => { + let character: char = '='; + return UpdateResult::Input(character); + } + Keycode::Greater => { + let character: char = '>'; + return UpdateResult::Input(character); + } + Keycode::Question => { + let character: char = '?'; + return UpdateResult::Input(character); + } + Keycode::At => { + let character: char = '@'; + return UpdateResult::Input(character); + } + Keycode::LeftBracket => { + let character: char = '['; + return UpdateResult::Input(character); + } + Keycode::Backslash => { + let character: char = '\\'; + return UpdateResult::Input(character); + } + Keycode::RightBracket => { + let character: char = ']'; + return UpdateResult::Input(character); + } + Keycode::Caret => { + let character: char = '^'; + return UpdateResult::Input(character); + } + Keycode::Underscore => { + let character: char = '_'; + return UpdateResult::Input(character); + } + Keycode::Backquote => { + let character: char = '`'; + return UpdateResult::Input(character); + } + Keycode::A => { + let character: char = if with_shift(event_pump) { 'A' } else { 'a' }; + return UpdateResult::Input(character); + } + Keycode::B => { + let character: char = if with_shift(event_pump) { 'B' } else { 'b' }; + return UpdateResult::Input(character); + } + Keycode::C => { + let character: char = if with_shift(event_pump) { 'C' } else { 'c' }; + return UpdateResult::Input(character); + } + Keycode::D => { + let character: char = if with_shift(event_pump) { 'D' } else { 'd' }; + return UpdateResult::Input(character); + } + Keycode::E => { + let character: char = if with_shift(event_pump) { 'E' } else { 'e' }; + return UpdateResult::Input(character); + } + Keycode::F => { + let character: char = if with_shift(event_pump) { 'F' } else { 'f' }; + return UpdateResult::Input(character); + } + Keycode::G => { + let character: char = if with_shift(event_pump) { 'G' } else { 'g' }; + return UpdateResult::Input(character); + } + Keycode::H => { + let character: char = if with_shift(event_pump) { 'H' } else { 'h' }; + return UpdateResult::Input(character); + } + Keycode::I => { + let character: char = if with_shift(event_pump) { 'I' } else { 'i' }; + return UpdateResult::Input(character); + } + Keycode::J => { + let character: char = if with_shift(event_pump) { 'J' } else { 'j' }; + return UpdateResult::Input(character); + } + Keycode::K => { + let character: char = if with_shift(event_pump) { 'K' } else { 'k' }; + return UpdateResult::Input(character); + } + Keycode::L => { + let character: char = if with_shift(event_pump) { 'L' } else { 'l' }; + return UpdateResult::Input(character); + } + Keycode::M => { + let character: char = if with_shift(event_pump) { 'M' } else { 'm' }; + return UpdateResult::Input(character); + } + Keycode::N => { + let character: char = if with_shift(event_pump) { 'N' } else { 'n' }; + return UpdateResult::Input(character); + } + Keycode::O => { + let character: char = if with_shift(event_pump) { 'O' } else { 'o' }; + return UpdateResult::Input(character); + } + Keycode::P => { + let character: char = if with_shift(event_pump) { 'P' } else { 'p' }; + return UpdateResult::Input(character); + } + Keycode::Q => { + let character: char = if with_shift(event_pump) { 'Q' } else { 'q' }; + return UpdateResult::Input(character); + } + Keycode::R => { + let character: char = if with_shift(event_pump) { 'R' } else { 'r' }; + return UpdateResult::Input(character); + } + Keycode::S => { + let character: char = if with_shift(event_pump) { 'S' } else { 's' }; + return UpdateResult::Input(character); + } + Keycode::T => { + let character: char = if with_shift(event_pump) { 'T' } else { 't' }; + return UpdateResult::Input(character); + } + Keycode::U => { + let character: char = if with_shift(event_pump) { 'U' } else { 'u' }; + return UpdateResult::Input(character); + } + Keycode::V => { + let character: char = if with_shift(event_pump) { 'V' } else { 'v' }; + return UpdateResult::Input(character); + } + Keycode::W => { + let character: char = if with_shift(event_pump) { 'W' } else { 'w' }; + return UpdateResult::Input(character); + } + Keycode::X => { + let character: char = if with_shift(event_pump) { 'X' } else { 'x' }; + return UpdateResult::Input(character); + } + Keycode::Y => { + let character: char = if with_shift(event_pump) { 'Y' } else { 'y' }; + return UpdateResult::Input(character); + } + Keycode::Z => { + let character: char = if with_shift(event_pump) { 'Z' } else { 'z' }; + return UpdateResult::Input(character); + } + _ => UpdateResult::NoOp + } +} + +fn with_shift(event_pump: &mut EventPump) -> bool { + event_pump.keyboard_state().is_scancode_pressed(Scancode::LShift) || + event_pump.keyboard_state().is_scancode_pressed(Scancode::RShift) +} diff --git a/src/app/mod.rs b/src/app/mod.rs index 5a26d0b..dcb3851 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -3,9 +3,11 @@ use crate::config::Config; use crate::renderer::Renderer; use crate::themes::*; use crate::ui::*; + use sdl2::{Sdl, TimerSubsystem}; use sdl2::event::Event; use sdl2::EventPump; +use sdl2::keyboard::{Keycode, Mod}; use sdl2::hint; use sdl2::mouse::MouseButton; use sdl2::pixels::Color; @@ -16,6 +18,7 @@ use std::thread::sleep; use std::time::Duration; pub mod app_state; +pub mod keyboard_handler; pub type WindowCanvas = Canvas; @@ -25,7 +28,10 @@ pub enum UpdateResult { Stop, RefreshPositions, MouseLeftClicked(Point), - MoveCaret(Rect), + MoveCaret(Rect, usize), + DeleteFront, + DeleteBack, + Input(char) } pub enum Task { @@ -86,15 +92,24 @@ impl Application { UpdateResult::Stop => break 'running, UpdateResult::RefreshPositions => (), UpdateResult::NoOp => (), - UpdateResult::MoveCaret(_) => (), + UpdateResult::MoveCaret(_, _pos) => (), UpdateResult::MouseLeftClicked(point) => { app_state.on_left_click(&point, renderer.config()); } + UpdateResult::DeleteFront => { + app_state.delete_front(renderer.config()); + }, + UpdateResult::DeleteBack => { + app_state.delete_back(renderer.config()); + }, + UpdateResult::Input(text_character) => { + app_state.insert_character(text_character, &mut renderer); + }, } for task in self.tasks.iter() { match task { Task::OpenFile { file_path } => { - use crate::file::editor_file::*; + use crate::ui::file::editor_file::*; app_state.open_file(file_path.clone(), renderer.config()); } } @@ -134,6 +149,17 @@ impl Application { MouseButton::Left => return UpdateResult::MouseLeftClicked(Point::new(x, y)), _ => (), }, + Event::KeyDown { keycode, .. } => { + let keycode = if keycode.is_some() { + keycode.unwrap() + } else { + return UpdateResult::NoOp; + }; + return keyboard_handler::resolve_action( + keycode, + event_pump + ); + } _ => (), } } diff --git a/src/main.rs b/src/main.rs index 4ef6445..c68c3b3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,6 @@ use crate::app::Application; pub mod app; pub mod config; -pub mod file; pub mod lexer; pub mod renderer; pub mod themes; diff --git a/src/ui/caret.rs b/src/ui/caret.rs index a2431a1..08eb7ae 100644 --- a/src/ui/caret.rs +++ b/src/ui/caret.rs @@ -14,12 +14,14 @@ enum CaretState { } pub struct Caret { - state: CaretState, + pending: bool, + text_position: usize, blink_delay: u8, - position: Rect, + state: CaretState, + dest: Rect, + reset_position: Rect, bright_character_color: Color, blur_character_color: Color, - pending: bool, } impl Caret { @@ -29,7 +31,13 @@ impl Caret { Self { state: CaretState::Bright, blink_delay: 0, - position: Rect::new( + dest: Rect::new( + config.editor_left_margin(), + config.editor_top_margin(), + 4, + 0, + ), + reset_position: Rect::new( config.editor_left_margin(), config.editor_top_margin(), 4, @@ -38,6 +46,7 @@ impl Caret { bright_character_color, blur_character_color, pending: true, + text_position: 0, } } @@ -49,9 +58,19 @@ impl Caret { }; } - pub fn move_caret(&mut self, pos: Point) { - self.position.set_x(pos.x()); - self.position.set_y(pos.y()); + pub fn reset_caret(&mut self) { + self.dest = self.reset_position.clone(); + self.text_position = 0; + } + + pub fn move_caret(&mut self, position: usize, pos: Point) { + self.text_position = position; + self.dest.set_x(pos.x()); + self.dest.set_y(pos.y()); + } + + pub fn text_position(&self) -> usize { + self.text_position } } @@ -68,14 +87,15 @@ impl Render for Caret { }) .unwrap_or_else(|_| panic!("Unable to load font")); if let Ok((_, h)) = font.size_of_char('W') { - self.position.set_height(h); + self.dest.set_height(h); + self.reset_position = self.dest.clone(); } self.pending = false; } - let start = Point::new(self.position.x(), self.position.y()); + let start = Point::new(self.dest.x(), self.dest.y()); let end = Point::new( - self.position.x(), - self.position.y() + self.position.height() as i32, + self.dest.x(), + self.dest.y() + self.dest.height() as i32, ); let color = match self.state { CaretState::Bright => &self.bright_character_color, @@ -107,6 +127,6 @@ impl ClickHandler for Caret { } fn is_left_click_target(&self, point: &Point) -> bool { - is_in_rect(point, &self.position) + is_in_rect(point, &self.dest) } } diff --git a/src/file/editor_file.rs b/src/ui/file/editor_file.rs similarity index 76% rename from src/file/editor_file.rs rename to src/ui/file/editor_file.rs index 04ebb8e..bc74a40 100644 --- a/src/file/editor_file.rs +++ b/src/ui/file/editor_file.rs @@ -1,30 +1,52 @@ +use sdl2::rect::{Point, Rect}; + use crate::app::{UpdateResult, WindowCanvas}; use crate::config::Config; -use crate::file::editor_file_section::EditorFileSection; +use crate::ui::file::editor_file_section::EditorFileSection; use crate::renderer::Renderer; use crate::ui::*; -use sdl2::rect::{Point, Rect}; +use crate::ui::text_character::TextCharacter; #[derive(Clone)] pub struct EditorFile { path: String, sections: Vec, render_position: Rect, + buffer: String, } impl EditorFile { pub fn new(path: String, buffer: String, config: &Config) -> Self { - let section = EditorFileSection::new(buffer, config); - let sections = vec![section]; + let sections = vec![ + EditorFileSection::new(buffer.clone(), config) + ]; let x = config.editor_left_margin(); let y = config.editor_top_margin(); Self { path, sections, render_position: Rect::new(x, y, 0, 0), + buffer } } + pub fn buffer(&self) -> String { + self.buffer.clone() + } + + pub fn path(&self) -> String { + self.path.clone() + } + + pub fn get_character_at(&self, index: usize) -> Option<&TextCharacter> { + for section in self.sections.iter() { + if let Some(text_character) = section.get_character_at(index) { + return Some(text_character) + } + } + None + } + fn refresh_characters_position(&mut self, config: &Config) { let mut current: Rect = self.render_position.clone(); for section in self.sections.iter_mut() { diff --git a/src/file/editor_file_section.rs b/src/ui/file/editor_file_section.rs similarity index 85% rename from src/file/editor_file_section.rs rename to src/ui/file/editor_file_section.rs index 44ec921..a00e8c7 100644 --- a/src/file/editor_file_section.rs +++ b/src/ui/file/editor_file_section.rs @@ -1,10 +1,12 @@ +use sdl2::rect::{Point, Rect}; + use crate::app::{UpdateResult, WindowCanvas}; use crate::config::Config; -use crate::file::editor_file_token::EditorFileToken; +use crate::ui::file::editor_file_token::EditorFileToken; use crate::lexer::Language; use crate::renderer::Renderer; use crate::ui::*; -use sdl2::rect::{Point, Rect}; +use crate::ui::text_character::TextCharacter; #[derive(Clone)] pub struct EditorFileSection { @@ -31,6 +33,15 @@ impl EditorFileSection { c.update_position(current, config); } } + + pub fn get_character_at(&self, index: usize) -> Option<&TextCharacter> { + for token in self.tokens.iter() { + if let Some(text_character) = token.get_character_at(index) { + return Some(text_character) + } + } + None + } } impl Render for EditorFileSection { diff --git a/src/file/editor_file_token.rs b/src/ui/file/editor_file_token.rs similarity index 86% rename from src/file/editor_file_token.rs rename to src/ui/file/editor_file_token.rs index cd50be5..11cfbb9 100644 --- a/src/file/editor_file_token.rs +++ b/src/ui/file/editor_file_token.rs @@ -31,6 +31,15 @@ impl EditorFileToken { } } + pub fn get_character_at(&self, index: usize) -> Option<&TextCharacter> { + for character in self.characters.iter() { + if character.position() == index { + return Some(&character) + } + } + None + } + fn update_view(&mut self, renderer: &mut Renderer) -> UpdateResult { let config = renderer.config().theme().code_highlighting(); let color: Color = match self.token_type { @@ -44,9 +53,13 @@ impl EditorFileToken { TokenType::Operator { .. } => config.operator().color().into(), TokenType::Separator { .. } => config.separator().color().into(), }; - for c in self.token_type.text().chars() { - let mut text_character = - TextCharacter::new(c.clone(), self.token_type.line(), color.clone()); + for (index, c) in self.token_type.text().chars().enumerate() { + let mut text_character = TextCharacter::new( + c.clone(), + self.token_type.start() + index, + self.token_type.line(), + color.clone() + ); text_character.update_view(renderer); self.characters.push(text_character); } diff --git a/src/file/mod.rs b/src/ui/file/mod.rs similarity index 100% rename from src/file/mod.rs rename to src/ui/file/mod.rs diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 576465a..620ef81 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,11 +1,14 @@ +use sdl2::rect::{Point, Rect}; + use crate::app::{UpdateResult, WindowCanvas}; use crate::config::Config; use crate::renderer::Renderer; -use sdl2::rect::{Point, Rect}; +use crate::renderer::managers::FontDetails; pub mod caret; pub mod menu_bar; pub mod text_character; +pub mod file; pub fn is_in_rect(point: &Point, rect: &Rect) -> bool { let start = Point::new(rect.x(), rect.y()); @@ -16,6 +19,22 @@ pub fn is_in_rect(point: &Point, rect: &Rect) -> bool { start.x() <= point.x() && start.y() <= point.y() && end.x() >= point.x() && end.y() >= point.y() } +pub fn get_text_character_rect(c: char, renderer: &mut Renderer) -> Option { + let config = renderer.config().editor_config(); + let font_details = + FontDetails::new(config.font_path().as_str(), config.character_size().clone()); + let font = renderer + .font_manager() + .load(&font_details) + .unwrap_or_else(|_| panic!("Font not found {:?}", font_details)); + + if let Ok((width, height)) = font.size_of_char(c) { + Some(Rect::new(0, 0, width, height)) + } else { + None + } +} + pub trait Render { fn render(&mut self, canvas: &mut WindowCanvas, renderer: &mut Renderer) -> UpdateResult; } diff --git a/src/ui/text_character.rs b/src/ui/text_character.rs index 69ae107..c009d60 100644 --- a/src/ui/text_character.rs +++ b/src/ui/text_character.rs @@ -5,8 +5,9 @@ use crate::renderer::managers::FontDetails; use crate::renderer::managers::TextDetails; use crate::renderer::Renderer; use crate::ui::*; + use sdl2::pixels::Color; -use sdl2::rect::Rect; +use sdl2::rect::{Rect, Point}; use sdl2::render::Texture; use sdl2::ttf::Font; use std::rc::Rc; @@ -15,6 +16,7 @@ use std::rc::Rc; pub struct TextCharacter { pending: bool, text_character: char, + position: usize, line: usize, source: Rect, dest: Rect, @@ -22,10 +24,11 @@ pub struct TextCharacter { } impl TextCharacter { - pub fn new(text_character: char, line: usize, color: Color) -> Self { + pub fn new(text_character: char, position: usize, line: usize, color: Color) -> Self { Self { pending: true, text_character, + position, line, source: Rect::new(0, 0, 0, 0), dest: Rect::new(0, 0, 0, 0), @@ -68,20 +71,19 @@ impl TextCharacter { .load(&font_details) .unwrap_or_else(|_| panic!("Font not found {:?}", font_details)); - let c = self.text_character.clone(); - if let Ok((width, height)) = font.size_of_char(c) { - self.source = Rect::new(0, 0, width, height); - self.dest = Rect::new(0, 0, width, height); + if let Some(rect) = get_text_character_rect(self.text_character.clone(), renderer) { + self.source = rect.clone(); + self.dest = rect.clone(); } let mut details = TextDetails { - text: c.to_string(), + text: self.text_character.to_string(), color: self.color.clone(), font: font_details.clone(), }; renderer .texture_manager() .load_text(&mut details, &font) - .unwrap_or_else(|_| panic!("Could not create texture for {:?}", c)); + .unwrap_or_else(|_| panic!("Could not create texture for {:?}", self.text_character)); self.pending = false; UpdateResult::RefreshPositions @@ -96,6 +98,10 @@ impl TextCharacter { pub fn is_pending(&self) -> bool { self.pending } + + pub fn position(&self) -> usize { + self.position + } } impl Render for TextCharacter { @@ -140,7 +146,10 @@ impl Update for TextCharacter { impl ClickHandler for TextCharacter { fn on_left_click(&mut self, _point: &Point, _config: &Config) -> UpdateResult { - UpdateResult::MoveCaret(self.dest().clone()) + UpdateResult::MoveCaret( + self.dest().clone(), + self.position() + ) } fn is_left_click_target(&self, point: &Point) -> bool {