use crate::display::display_color::DisplayColor;
use crate::input::input_handler::InputMode;
use crate::input::Input;
use crate::process::process_module::ProcessModule;
use crate::process::process_result::ProcessResult;
use crate::process::state::State;
use crate::todo_file::edit_content::EditContext;
use crate::todo_file::TodoFile;
use crate::view::line_segment::LineSegment;
use crate::view::view_data::ViewData;
use crate::view::view_line::ViewLine;
use crate::view::View;
use unicode_segmentation::UnicodeSegmentation;
pub struct Edit {
content: String,
cursor_position: usize,
view_data: ViewData,
}
impl ProcessModule for Edit {
fn activate(&mut self, todo_file: &TodoFile, _: State) -> ProcessResult {
self.content = todo_file.get_selected_line().get_edit_content().to_string();
self.cursor_position = UnicodeSegmentation::graphemes(self.content.as_str(), true).count();
ProcessResult::new()
}
fn deactivate(&mut self) {
self.content.clear();
self.view_data.clear();
}
fn build_view_data(&mut self, view: &View<'_>, _: &TodoFile) -> &ViewData {
let view_width = view.get_view_size().width();
let view_height = view.get_view_size().height();
let line = self.content.as_str();
let pointer = self.cursor_position;
let graphemes = UnicodeSegmentation::graphemes(line, true);
let start = graphemes.clone().take(pointer).collect::<String>();
let indicator = graphemes.clone().skip(pointer).take(1).collect::<String>();
let end = graphemes.skip(pointer + 1).collect::<String>();
let mut segments = vec![
LineSegment::new(start.as_str()),
LineSegment::new_with_color_and_style(indicator.as_str(), DisplayColor::Normal, false, true, false),
LineSegment::new(end.as_str()),
];
if indicator.is_empty() {
segments.push(LineSegment::new_with_color_and_style(
" ",
DisplayColor::Normal,
false,
true,
false,
));
}
self.view_data.clear();
self.view_data.push_line(ViewLine::from(segments));
self.view_data
.push_trailing_line(ViewLine::new_pinned(vec![LineSegment::new_with_color(
"Enter to finish",
DisplayColor::IndicatorColor,
)]));
self.view_data.set_view_size(view_width, view_height);
self.view_data.rebuild();
self.view_data.ensure_column_visible(pointer);
&self.view_data
}
fn handle_input(&mut self, view: &View<'_>, todo_file: &mut TodoFile) -> ProcessResult {
let result = loop {
let input = view.get_input(InputMode::Raw);
let result = ProcessResult::new().input(input);
match input {
Input::Character(c) => {
let start = UnicodeSegmentation::graphemes(self.content.as_str(), true)
.take(self.cursor_position)
.collect::<String>();
let end = UnicodeSegmentation::graphemes(self.content.as_str(), true)
.skip(self.cursor_position)
.collect::<String>();
self.content = format!("{}{}{}", start, c, end);
self.cursor_position += 1;
},
Input::Backspace => {
if self.cursor_position != 0 {
let start = UnicodeSegmentation::graphemes(self.content.as_str(), true)
.take(self.cursor_position - 1)
.collect::<String>();
let end = UnicodeSegmentation::graphemes(self.content.as_str(), true)
.skip(self.cursor_position)
.collect::<String>();
self.content = format!("{}{}", start, end);
self.cursor_position -= 1;
}
},
Input::Delete => {
let length = UnicodeSegmentation::graphemes(self.content.as_str(), true).count();
if self.cursor_position != length {
let start = UnicodeSegmentation::graphemes(self.content.as_str(), true)
.take(self.cursor_position)
.collect::<String>();
let end = UnicodeSegmentation::graphemes(self.content.as_str(), true)
.skip(self.cursor_position + 1)
.collect::<String>();
self.content = format!("{}{}", start, end);
}
},