diff --git a/Cargo.lock b/Cargo.lock index e09a588..0412504 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1837,7 +1837,7 @@ dependencies = [ [[package]] name = "freya" version = "0.2.2" -source = "git+https://github.com/marc2332/freya?rev=1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1#1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" +source = "git+https://github.com/marc2332/freya?rev=523a9d98339c356d4edc43fec7f87ba35c3ffe59#523a9d98339c356d4edc43fec7f87ba35c3ffe59" dependencies = [ "dioxus", "dioxus-core", @@ -1860,7 +1860,7 @@ dependencies = [ [[package]] name = "freya-common" version = "0.2.1" -source = "git+https://github.com/marc2332/freya?rev=1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1#1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" +source = "git+https://github.com/marc2332/freya?rev=523a9d98339c356d4edc43fec7f87ba35c3ffe59#523a9d98339c356d4edc43fec7f87ba35c3ffe59" dependencies = [ "accesskit", "dioxus-core", @@ -1876,7 +1876,7 @@ dependencies = [ [[package]] name = "freya-components" version = "0.2.1" -source = "git+https://github.com/marc2332/freya?rev=1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1#1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" +source = "git+https://github.com/marc2332/freya?rev=523a9d98339c356d4edc43fec7f87ba35c3ffe59#523a9d98339c356d4edc43fec7f87ba35c3ffe59" dependencies = [ "bytes", "dioxus", @@ -1899,7 +1899,7 @@ dependencies = [ [[package]] name = "freya-core" version = "0.2.1" -source = "git+https://github.com/marc2332/freya?rev=1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1#1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" +source = "git+https://github.com/marc2332/freya?rev=523a9d98339c356d4edc43fec7f87ba35c3ffe59#523a9d98339c356d4edc43fec7f87ba35c3ffe59" dependencies = [ "accesskit", "accesskit_winit", @@ -1922,7 +1922,7 @@ dependencies = [ [[package]] name = "freya-elements" version = "0.2.0" -source = "git+https://github.com/marc2332/freya?rev=1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1#1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" +source = "git+https://github.com/marc2332/freya?rev=523a9d98339c356d4edc43fec7f87ba35c3ffe59#523a9d98339c356d4edc43fec7f87ba35c3ffe59" dependencies = [ "dioxus-core", "dioxus-rsx", @@ -1934,7 +1934,7 @@ dependencies = [ [[package]] name = "freya-engine" version = "0.2.2" -source = "git+https://github.com/marc2332/freya?rev=1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1#1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" +source = "git+https://github.com/marc2332/freya?rev=523a9d98339c356d4edc43fec7f87ba35c3ffe59#523a9d98339c356d4edc43fec7f87ba35c3ffe59" dependencies = [ "bitflags 2.6.0", "glutin", @@ -1944,7 +1944,7 @@ dependencies = [ [[package]] name = "freya-hooks" version = "0.2.1" -source = "git+https://github.com/marc2332/freya?rev=1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1#1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" +source = "git+https://github.com/marc2332/freya?rev=523a9d98339c356d4edc43fec7f87ba35c3ffe59#523a9d98339c356d4edc43fec7f87ba35c3ffe59" dependencies = [ "bitflags 2.6.0", "bytes", @@ -1969,7 +1969,7 @@ dependencies = [ [[package]] name = "freya-native-core" version = "0.2.1" -source = "git+https://github.com/marc2332/freya?rev=1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1#1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" +source = "git+https://github.com/marc2332/freya?rev=523a9d98339c356d4edc43fec7f87ba35c3ffe59#523a9d98339c356d4edc43fec7f87ba35c3ffe59" dependencies = [ "anymap", "dashmap", @@ -1983,7 +1983,7 @@ dependencies = [ [[package]] name = "freya-native-core-macro" version = "0.2.0" -source = "git+https://github.com/marc2332/freya?rev=1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1#1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" +source = "git+https://github.com/marc2332/freya?rev=523a9d98339c356d4edc43fec7f87ba35c3ffe59#523a9d98339c356d4edc43fec7f87ba35c3ffe59" dependencies = [ "quote", "syn 2.0.72", @@ -1992,7 +1992,7 @@ dependencies = [ [[package]] name = "freya-node-state" version = "0.2.1" -source = "git+https://github.com/marc2332/freya?rev=1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1#1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" +source = "git+https://github.com/marc2332/freya?rev=523a9d98339c356d4edc43fec7f87ba35c3ffe59#523a9d98339c356d4edc43fec7f87ba35c3ffe59" dependencies = [ "accesskit", "bytes", @@ -2013,7 +2013,7 @@ dependencies = [ [[package]] name = "freya-renderer" version = "0.2.1" -source = "git+https://github.com/marc2332/freya?rev=1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1#1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" +source = "git+https://github.com/marc2332/freya?rev=523a9d98339c356d4edc43fec7f87ba35c3ffe59#523a9d98339c356d4edc43fec7f87ba35c3ffe59" dependencies = [ "accesskit", "accesskit_winit", @@ -5067,7 +5067,7 @@ dependencies = [ [[package]] name = "torin" version = "0.2.0" -source = "git+https://github.com/marc2332/freya?rev=1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1#1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" +source = "git+https://github.com/marc2332/freya?rev=523a9d98339c356d4edc43fec7f87ba35c3ffe59#523a9d98339c356d4edc43fec7f87ba35c3ffe59" dependencies = [ "euclid", "freya-native-core", diff --git a/Cargo.toml b/Cargo.toml index bb41e57..54925f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" dioxus-sdk = { git = "https://github.com/DioxusLabs/sdk", rev = "57ab3fa972c6d4a7acc25e82a0aafc3ff9e63403" } [dependencies] -freya-node-state = { git = "https://github.com/marc2332/freya", rev = "1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" } -freya = { git = "https://github.com/marc2332/freya", rev = "1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" } -freya-hooks = { git = "https://github.com/marc2332/freya", rev = "1b1a24a84e2a80bffc3d439ae023cb9a812ec1b1" } +freya-node-state = { git = "https://github.com/marc2332/freya", rev = "523a9d98339c356d4edc43fec7f87ba35c3ffe59" } +freya = { git = "https://github.com/marc2332/freya", rev = "523a9d98339c356d4edc43fec7f87ba35c3ffe59" } +freya-hooks = { git = "https://github.com/marc2332/freya", rev = "523a9d98339c356d4edc43fec7f87ba35c3ffe59" } dioxus-radio = "0.2.4" dioxus = "0.5" diff --git a/src/components/tab.rs b/src/components/tab.rs index a885c1a..623a60c 100644 --- a/src/components/tab.rs +++ b/src/components/tab.rs @@ -11,7 +11,7 @@ pub fn EditorTab( is_edited: bool, ) -> Element { let mut status = use_signal(ButtonStatus::default); - let theme = use_get_theme(); + let theme = use_applied_theme!(None, button); let platform = use_platform(); use_drop(move || { @@ -35,7 +35,7 @@ pub fn EditorTab( ButtonStatus::Hovering => "rgb(30, 30, 30)", ButtonStatus::Idle => "transparent", }; - let color = theme.button.font_theme.color; + let color = theme.font_theme.color; let selected_color = if is_selected { "rgb(60, 60, 60)" } else { diff --git a/src/hooks/use_edit.rs b/src/hooks/use_edit.rs index e1c5b5f..0379949 100644 --- a/src/hooks/use_edit.rs +++ b/src/hooks/use_edit.rs @@ -1,5 +1,4 @@ use dioxus::dioxus_core::AttributeValue; -use dioxus_use_computed::hooks::use_computed; use freya::core::prelude::{EventMessage, TextGroupMeasurement}; use crate::tabs::editor::AppStateEditorUtils; @@ -172,9 +171,9 @@ pub fn use_edit(radio: &RadioAppState, panel_index: usize, tab_index: usize) -> let platform = use_platform(); let mut cursor_receiver_task = use_signal::>(|| None); - let cursor_reference = use_computed((panel_index, tab_index), { + let cursor_reference = use_memo(use_reactive(&(panel_index, tab_index), { to_owned![radio]; - move || { + move |(panel_index, tab_index)| { if let Some(cursor_receiver_task) = cursor_receiver_task.write_unchecked().take() { cursor_receiver_task.cancel(); } @@ -200,16 +199,15 @@ pub fn use_edit(radio: &RadioAppState, panel_index: usize, tab_index: usize) -> id, ); - // Only update if it's actually different - if editor_tab.editor.cursor != new_cursor { + // Only update and clear the selection if the cursor has changed + if editor_tab.editor.cursor() != new_cursor { let editor_tab = app_state.editor_tab_mut(panel_index, tab_index); *editor_tab.editor.cursor_mut() = new_cursor; - if let TextDragging::FromCursorToPoint { cursor: from, .. } = - dragging() + &*dragging.read() { let to = editor_tab.editor.cursor_pos(); - editor_tab.editor.set_selection((from, to)); + editor_tab.editor.set_selection((*from, to)); } else { editor_tab.editor.clear_selection(); } @@ -218,34 +216,26 @@ pub fn use_edit(radio: &RadioAppState, panel_index: usize, tab_index: usize) -> // Update the text selections calculated by the layout CursorLayoutResponse::TextSelection { from, to, id } => { let mut app_state = radio.write(); - let editor_tab = app_state.editor_tab(panel_index, tab_index); + let editor_tab = app_state.editor_tab_mut(panel_index, tab_index); let current_cursor = editor_tab.editor.cursor().clone(); let current_selection = editor_tab.editor.get_selection(); let maybe_new_cursor = editor_tab.editor.measure_new_cursor(to, id); - let (from, to) = ( - editor_tab.editor.utf16_cu_to_char(from), - editor_tab.editor.utf16_cu_to_char(to), - ); let maybe_new_selection = editor_tab.editor.measure_new_selection(from, to, id); // Update the text selection if it has changed if let Some(current_selection) = current_selection { if current_selection != maybe_new_selection { - let editor_tab = - app_state.editor_tab_mut(panel_index, tab_index); editor_tab.editor.set_selection(maybe_new_selection); } } else { - let editor_tab = app_state.editor_tab_mut(panel_index, tab_index); editor_tab.editor.set_selection(maybe_new_selection); } // Update the cursor if it has changed if current_cursor != maybe_new_cursor { - let editor_tab = app_state.editor_tab_mut(panel_index, tab_index); *editor_tab.editor.cursor_mut() = maybe_new_cursor; } } @@ -257,7 +247,7 @@ pub fn use_edit(radio: &RadioAppState, panel_index: usize, tab_index: usize) -> cursor_reference } - }); + })); UseEdit { radio: *radio, diff --git a/src/parser.rs b/src/parser.rs index b4ea6c0..20b5a18 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,5 +1,6 @@ use std::{borrow::Cow, ops::Range}; +use fxhash::FxHashMap; use ropey::Rope; use smallvec::SmallVec; @@ -60,16 +61,16 @@ pub type SyntaxLine = SmallVec<[(SyntaxType, TextNode); 4]>; #[derive(Default)] pub struct SyntaxBlocks { - blocks: Vec, + blocks: FxHashMap, } impl SyntaxBlocks { pub fn push_line(&mut self, line: SyntaxLine) { - self.blocks.push(line); + self.blocks.insert(self.len(), line); } pub fn get_line(&self, line: usize) -> &[(SyntaxType, TextNode)] { - &self.blocks[line] + self.blocks.get(&line).unwrap() } pub fn len(&self) -> usize { diff --git a/src/tabs/editor/editor_data.rs b/src/tabs/editor/editor_data.rs index cbf8c89..b2c8ebb 100644 --- a/src/tabs/editor/editor_data.rs +++ b/src/tabs/editor/editor_data.rs @@ -153,29 +153,60 @@ impl TextEditor for EditorData { unimplemented!("Unused.") } - fn insert_char(&mut self, char: char, char_idx: usize) { + fn insert_char(&mut self, ch: char, idx: usize) -> usize { + let idx_utf8 = self.utf16_cu_to_char(idx); + + let len_before_insert = self.len_utf16_cu(); + self.rope.borrow_mut().insert_char(idx_utf8, ch); + let len_after_insert = self.len_utf16_cu(); + + let inserted_text_len = len_after_insert - len_before_insert; + self.history.push_change(HistoryChange::InsertChar { - idx: char_idx, - char, + idx, + ch, + len: inserted_text_len, }); - self.rope.borrow_mut().insert_char(char_idx, char); + + inserted_text_len } - fn insert(&mut self, text: &str, idx: usize) { + fn insert(&mut self, text: &str, idx: usize) -> usize { + let idx_utf8 = self.utf16_cu_to_char(idx); + + let len_before_insert = self.len_utf16_cu(); + self.rope.borrow_mut().insert(idx_utf8, text); + let len_after_insert = self.len_utf16_cu(); + + let inserted_text_len = len_after_insert - len_before_insert; + self.history.push_change(HistoryChange::InsertText { idx, text: text.to_owned(), + len: inserted_text_len, }); - self.rope.borrow_mut().insert(idx, text); + + inserted_text_len } - fn remove(&mut self, range: Range) { + fn remove(&mut self, range_utf16: Range) -> usize { + let range = + self.utf16_cu_to_char(range_utf16.start)..self.utf16_cu_to_char(range_utf16.end); let text = self.rope.borrow().slice(range.clone()).to_string(); + + let len_before_remove = self.len_utf16_cu(); + self.rope.borrow_mut().remove(range); + let len_after_remove = self.len_utf16_cu(); + + let removed_text_len = len_before_remove - len_after_remove; + self.history.push_change(HistoryChange::Remove { - idx: range.start, + idx: range_utf16.end - removed_text_len, text, + len: removed_text_len, }); - self.rope.borrow_mut().remove(range) + + removed_text_len } fn char_to_line(&self, char_idx: usize) -> usize { @@ -200,6 +231,7 @@ impl TextEditor for EditorData { line.map(|line| Line { text: Cow::Owned(line.to_string()), + utf16_len: line.len_utf16_cu(), }) } @@ -211,6 +243,10 @@ impl TextEditor for EditorData { self.rope.borrow().len_chars() } + fn len_utf16_cu(&self) -> usize { + self.rope.borrow().len_utf16_cu() + } + fn cursor(&self) -> &TextCursor { &self.cursor } @@ -238,25 +274,21 @@ impl TextEditor for EditorData { fn get_visible_selection(&self, editor_id: usize) -> Option<(usize, usize)> { let (selected_from, selected_to) = self.selected?; + let selected_from_row = self.char_to_line(self.utf16_cu_to_char(selected_from)); + let selected_to_row = self.char_to_line(self.utf16_cu_to_char(selected_to)); - let selected_to_row = self.char_to_line(selected_to); - let selected_from_row = self.char_to_line(selected_from); + let editor_row_idx = self.char_to_utf16_cu(self.line_to_char(editor_id)); + let selected_from_row_idx = self.char_to_utf16_cu(self.line_to_char(selected_from_row)); + let selected_to_row_idx = self.char_to_utf16_cu(self.line_to_char(selected_to_row)); - let selected_to_line = self.char_to_line(selected_to); - let selected_from_line = self.char_to_line(selected_from); - - let editor_row_idx = self.line_to_char(editor_id); - let selected_to_row_idx = self.line_to_char(selected_to_line); - let selected_from_row_idx = self.line_to_char(selected_from_line); - - let selected_to_col_idx = selected_to - selected_to_row_idx; let selected_from_col_idx = selected_from - selected_from_row_idx; + let selected_to_col_idx = selected_to - selected_to_row_idx; // Between starting line and endling line if (editor_id > selected_from_row && editor_id < selected_to_row) || (editor_id < selected_from_row && editor_id > selected_to_row) { - let len = self.line(editor_id).unwrap().len_chars(); + let len = self.line(editor_id).unwrap().utf16_len(); return Some((0, len)); } @@ -268,7 +300,7 @@ impl TextEditor for EditorData { Some((0, selected_from_col_idx)) } else if selected_to_row == editor_id { // Ending line - let len = self.line(selected_to_row).unwrap().len_chars(); + let len = self.line(selected_to_row).unwrap().utf16_len(); Some((selected_to_col_idx, len)) } else { None @@ -278,7 +310,7 @@ impl TextEditor for EditorData { Ordering::Less => { if selected_from_row == editor_id { // Starting line - let len = self.line(selected_from_row).unwrap().len_chars(); + let len = self.line(selected_from_row).unwrap().utf16_len(); Some((selected_from_col_idx, len)) } else if selected_to_row == editor_id { // Ending line @@ -287,17 +319,14 @@ impl TextEditor for EditorData { None } } - Ordering::Equal => { + Ordering::Equal if selected_from_row == editor_id => { // Starting and endline line are the same - if selected_from_row == editor_id { - Some((selected_from - editor_row_idx, selected_to - editor_row_idx)) - } else { - None - } + Some((selected_from - editor_row_idx, selected_to - editor_row_idx)) } + _ => None, }; - highlights.map(|(from, to)| (self.char_to_utf16_cu(from), self.char_to_utf16_cu(to))) + highlights } fn set(&mut self, text: &str) { @@ -311,6 +340,7 @@ impl TextEditor for EditorData { fn measure_new_selection(&self, from: usize, to: usize, editor_id: usize) -> (usize, usize) { let row_idx = self.line_to_char(editor_id); + let row_idx = self.char_to_utf16_cu(row_idx); if let Some((start, _)) = self.selected { (start, row_idx + to) } else { @@ -320,7 +350,7 @@ impl TextEditor for EditorData { fn measure_new_cursor(&self, to: usize, editor_id: usize) -> TextCursor { let row_char = self.line_to_char(editor_id); - let pos = row_char + to; + let pos = self.char_to_utf16_cu(row_char) + to; TextCursor::new(pos) }