diff --git a/crates/core/src/dom/doms.rs b/crates/core/src/dom/doms.rs index 847e76414..7886c2006 100644 --- a/crates/core/src/dom/doms.rs +++ b/crates/core/src/dom/doms.rs @@ -215,7 +215,7 @@ impl FreyaDOM { let node = rdom.get(*node_id); let layout_node = layout.get(*node_id); if let Some((node, layout_node)) = node.zip(layout_node) { - measure_paragraph(&node, layout_node, true, scale_factor); + measure_paragraph(&node, layout_node, scale_factor); } } } @@ -232,7 +232,7 @@ impl FreyaDOM { let layout_node = layout.get(*node_id); if let Some((node, layout_node)) = node.zip(layout_node) { - measure_paragraph(&node, layout_node, true, scale_factor); + measure_paragraph(&node, layout_node, scale_factor); } } } diff --git a/crates/core/src/dom/paragraph_utils.rs b/crates/core/src/dom/paragraph_utils.rs index 1c4e9b1f0..8936b2370 100644 --- a/crates/core/src/dom/paragraph_utils.rs +++ b/crates/core/src/dom/paragraph_utils.rs @@ -1,92 +1,83 @@ -use freya_native_core::real_dom::NodeImmutable; - -use freya_common::{CachedParagraph, CursorLayoutResponse}; -use freya_node_state::{CursorReference, CursorSettings}; -use std::ops::Mul; - -use torin::prelude::*; - -use crate::dom::DioxusNode; - -pub fn measure_paragraph( - node: &DioxusNode, - layout_node: &LayoutNode, - is_editable: bool, - scale_factor: f32, -) { - let paragraph = &layout_node - .data - .as_ref() - .unwrap() - .get::() - .unwrap() - .0; - let scale_factors = scale_factor as f64; - - if is_editable { - if let Some((cursor_ref, id, cursor_position, cursor_selections)) = - get_cursor_reference(node) - { - if let Some(cursor_position) = cursor_position { - // Calculate the new cursor position - let char_position = paragraph.get_glyph_position_at_coordinate( - cursor_position.mul(scale_factors).to_i32().to_tuple(), - ); - - // Notify the cursor reference listener - cursor_ref - .cursor_sender - .send(CursorLayoutResponse::CursorPosition { - position: char_position.position as usize, - id, - }) - .ok(); - } - - if let Some((origin, dist)) = cursor_selections { - // Calculate the start of the highlighting - let origin_char = paragraph.get_glyph_position_at_coordinate( - origin.mul(scale_factors).to_i32().to_tuple(), - ); - // Calculate the end of the highlighting - let dist_char = paragraph - .get_glyph_position_at_coordinate(dist.mul(scale_factors).to_i32().to_tuple()); - - cursor_ref - .cursor_sender - .send(CursorLayoutResponse::TextSelection { - from: origin_char.position as usize, - to: dist_char.position as usize, - id, - }) - .ok(); - } - } - } -} - -/// Get the info related to a cursor reference -#[allow(clippy::type_complexity)] -fn get_cursor_reference( - node: &DioxusNode, -) -> Option<( - CursorReference, - usize, - Option, - Option<(CursorPoint, CursorPoint)>, -)> { - let cursor_settings = node.get::().unwrap(); - - let cursor_ref = cursor_settings.cursor_ref.clone()?; - let cursor_id = cursor_settings.cursor_id?; - - let current_cursor_id = { *cursor_ref.cursor_id.lock().unwrap().as_ref()? }; - let cursor_selections = *cursor_ref.cursor_selections.lock().unwrap(); - let cursor_position = *cursor_ref.cursor_position.lock().unwrap(); - - if current_cursor_id == cursor_id { - Some((cursor_ref, cursor_id, cursor_position, cursor_selections)) - } else { - None - } -} +use freya_native_core::real_dom::NodeImmutable; + +use freya_common::{CachedParagraph, CursorLayoutResponse}; +use freya_node_state::{CursorReference, CursorSettings}; +use std::ops::Mul; + +use torin::prelude::*; + +use crate::dom::DioxusNode; + +pub fn measure_paragraph(node: &DioxusNode, layout_node: &LayoutNode, scale_factor: f32) { + let paragraph = &layout_node + .data + .as_ref() + .unwrap() + .get::() + .unwrap() + .0; + + let scale_factors = scale_factor as f64; + + if let Some((cursor_ref, id, cursor_position, cursor_selections)) = get_cursor_reference(node) { + if let Some(cursor_position) = cursor_position { + // Calculate the new cursor position + let char_position = paragraph.get_glyph_position_at_coordinate( + cursor_position.mul(scale_factors).to_i32().to_tuple(), + ); + + // Notify the cursor reference listener + cursor_ref + .cursor_sender + .send(CursorLayoutResponse::CursorPosition { + position: char_position.position as usize, + id, + }) + .ok(); + } + + if let Some((origin, dist)) = cursor_selections { + // Calculate the start of the highlighting + let origin_char = paragraph + .get_glyph_position_at_coordinate(origin.mul(scale_factors).to_i32().to_tuple()); + // Calculate the end of the highlighting + let dist_char = paragraph + .get_glyph_position_at_coordinate(dist.mul(scale_factors).to_i32().to_tuple()); + + cursor_ref + .cursor_sender + .send(CursorLayoutResponse::TextSelection { + from: origin_char.position as usize, + to: dist_char.position as usize, + id, + }) + .ok(); + } + } +} + +/// Get the info related to a cursor reference +#[allow(clippy::type_complexity)] +fn get_cursor_reference( + node: &DioxusNode, +) -> Option<( + CursorReference, + usize, + Option, + Option<(CursorPoint, CursorPoint)>, +)> { + let cursor_settings = node.get::().unwrap(); + + let cursor_ref = cursor_settings.cursor_ref.clone()?; + let cursor_id = cursor_settings.cursor_id?; + + let current_cursor_id = *cursor_ref.cursor_id.lock().unwrap().as_ref()?; + + if current_cursor_id == cursor_id { + let cursor_selections = cursor_ref.cursor_selections.lock().unwrap().take(); + let cursor_position = cursor_ref.cursor_position.lock().unwrap().take(); + Some((cursor_ref, cursor_id, cursor_position, cursor_selections)) + } else { + None + } +} diff --git a/crates/hooks/src/use_editable.rs b/crates/hooks/src/use_editable.rs index e8d506530..be6d83a2b 100644 --- a/crates/hooks/src/use_editable.rs +++ b/crates/hooks/src/use_editable.rs @@ -4,7 +4,6 @@ use std::{ }; use dioxus_core::{prelude::spawn, use_hook, AttributeValue}; -use dioxus_hooks::to_owned; use dioxus_sdk::clipboard::use_clipboard; use dioxus_signals::{Readable, Signal, Writable}; use freya_common::{CursorLayoutResponse, EventMessage}; @@ -180,70 +179,61 @@ pub fn use_editable(initializer: impl Fn() -> EditableConfig, mode: EditableMode cursor_selections: Arc::new(Mutex::new(None)), }; - spawn({ - to_owned![cursor_reference]; - async move { - while let Some(message) = cursor_receiver.recv().await { - match message { - // Update the cursor position calculated by the layout - CursorLayoutResponse::CursorPosition { position, id } => { - let mut text_editor = editor.write(); + spawn(async move { + while let Some(message) = cursor_receiver.recv().await { + match message { + // Update the cursor position calculated by the layout + CursorLayoutResponse::CursorPosition { position, id } => { + let mut text_editor = editor.write(); - let new_cursor_row = match mode { - EditableMode::MultipleLinesSingleEditor => { - text_editor.char_to_line(text_editor.utf16_cu_to_char(position)) - } - EditableMode::SingleLineMultipleEditors => id, - }; - - let new_cursor_col = match mode { - EditableMode::MultipleLinesSingleEditor => text_editor - .utf16_cu_to_char( - position - - text_editor.char_to_utf16_cu( - text_editor.line_to_char(new_cursor_row), - ), - ), - EditableMode::SingleLineMultipleEditors => { - text_editor.utf16_cu_to_char(position) - } - }; - - let new_current_line = text_editor.line(new_cursor_row).unwrap(); - - // Use the line length as new column if the clicked column surpases the length - let new_cursor = if new_cursor_col >= new_current_line.utf16_len_chars() - { - ( - text_editor - .utf16_cu_to_char(new_current_line.utf16_len_chars()), - new_cursor_row, - ) - } else { - (new_cursor_col, new_cursor_row) - }; - - // Only update if it's actually different - if text_editor.cursor().as_tuple() != new_cursor { - text_editor.cursor_mut().set_col(new_cursor.0); - text_editor.cursor_mut().set_row(new_cursor.1); - text_editor.unhighlight(); + let new_cursor_row = match mode { + EditableMode::MultipleLinesSingleEditor => { + text_editor.char_to_line(text_editor.utf16_cu_to_char(position)) } - - // Remove the current calcutions so the layout engine doesn't try to calculate again - cursor_reference.set_cursor_position(None); - } - // Update the text selections calculated by the layout - CursorLayoutResponse::TextSelection { from, to, id } => { - let mut text_editor = editor.write(); - let (from, to) = ( - text_editor.utf16_cu_to_char(from), - text_editor.utf16_cu_to_char(to), - ); - text_editor.highlight_text(from, to, id); - cursor_reference.set_cursor_selections(None); + EditableMode::SingleLineMultipleEditors => id, + }; + + let new_cursor_col = match mode { + EditableMode::MultipleLinesSingleEditor => text_editor + .utf16_cu_to_char( + position + - text_editor.char_to_utf16_cu( + text_editor.line_to_char(new_cursor_row), + ), + ), + EditableMode::SingleLineMultipleEditors => { + text_editor.utf16_cu_to_char(position) + } + }; + + let new_current_line = text_editor.line(new_cursor_row).unwrap(); + + // Use the line length as new column if the clicked column surpases the length + let new_cursor = if new_cursor_col >= new_current_line.utf16_len_chars() { + ( + text_editor.utf16_cu_to_char(new_current_line.utf16_len_chars()), + new_cursor_row, + ) + } else { + (new_cursor_col, new_cursor_row) + }; + + // Only update if it's actually different + if text_editor.cursor().as_tuple() != new_cursor { + text_editor.cursor_mut().set_col(new_cursor.0); + text_editor.cursor_mut().set_row(new_cursor.1); + text_editor.unhighlight(); } } + // Update the text selections calculated by the layout + CursorLayoutResponse::TextSelection { from, to, id } => { + let mut text_editor = editor.write(); + let (from, to) = ( + text_editor.utf16_cu_to_char(from), + text_editor.utf16_cu_to_char(to), + ); + text_editor.highlight_text(from, to, id); + } } } }); diff --git a/examples/simple_editor.rs b/examples/simple_editor.rs index 85f435629..964396049 100644 --- a/examples/simple_editor.rs +++ b/examples/simple_editor.rs @@ -6,7 +6,7 @@ use freya::prelude::*; fn main() { - launch(app); + launch_with_props(app, "Simple editor", (900.0, 650.0)); } fn app() -> Element {