mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-08 22:28:12 -05:00
app: various cleanups to Editor used by BaseEdit with main one being moving from async to purely sync. other changes:
* Removed `Option` wrapper from editor * Removed `EditorHandle` wrapper * Changed all editor locks to synchronous * Made all Editor methods synchronous * Created `ParleyDriverWrapper`. This makes using the driver much easier.
This commit is contained in:
@@ -73,16 +73,16 @@ impl Editor {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn on_text_prop_changed(&mut self) {
|
||||
pub fn on_text_prop_changed(&mut self) {
|
||||
// Update GameTextInput state
|
||||
self.state.text = self.text.get();
|
||||
self.state.select = (0, 0);
|
||||
self.state.compose = None;
|
||||
self.input.set_state(self.state.clone());
|
||||
// Refresh our layout
|
||||
self.refresh().await;
|
||||
self.refresh();
|
||||
}
|
||||
pub async fn on_buffer_changed(&mut self, atom: &mut PropertyAtomicGuard) {
|
||||
pub fn on_buffer_changed(&mut self, atom: &mut PropertyAtomicGuard) {
|
||||
// Only refresh layout if text content actually changed
|
||||
// Avoid triggering expensive recomputes of layout and property tree.
|
||||
let old_text = self.text.get();
|
||||
@@ -90,7 +90,7 @@ impl Editor {
|
||||
return
|
||||
}
|
||||
|
||||
self.refresh().await;
|
||||
self.refresh();
|
||||
// Update the text attribute
|
||||
self.text.set(atom, &self.state.text);
|
||||
}
|
||||
@@ -102,7 +102,7 @@ impl Editor {
|
||||
self.input.hide();
|
||||
}
|
||||
|
||||
pub async fn refresh(&mut self) {
|
||||
pub fn refresh(&mut self) {
|
||||
let font_size = self.font_size.get();
|
||||
let text_color = self.text_color.get();
|
||||
let window_scale = self.window_scale.get();
|
||||
@@ -139,7 +139,7 @@ impl Editor {
|
||||
self.input.set_select(cursor_idx, cursor_idx);
|
||||
}
|
||||
|
||||
pub async fn select_word_at_point(&mut self, pos: Point) {
|
||||
pub fn select_word_at_point(&mut self, pos: Point) {
|
||||
let select = parley::Selection::word_from_point(&self.layout, pos.x, pos.y);
|
||||
assert!(!select.is_collapsed());
|
||||
let select = select.text_range();
|
||||
@@ -163,7 +163,7 @@ impl Editor {
|
||||
Point::new(cursor_rect.x0 as f32, cursor_rect.y0 as f32)
|
||||
}
|
||||
|
||||
pub async fn insert(&mut self, txt: &str, atom: &mut PropertyAtomicGuard) {
|
||||
pub fn insert(&mut self, txt: &str, atom: &mut PropertyAtomicGuard) {
|
||||
// TODO: need to verify this is correct
|
||||
// Insert text by updating the state
|
||||
self.state.text.push_str(txt);
|
||||
@@ -214,7 +214,7 @@ impl Editor {
|
||||
|
||||
parley::Selection::new(anchor, focus)
|
||||
}
|
||||
pub async fn set_selection(&mut self, select_start: usize, select_end: usize) {
|
||||
pub fn set_selection(&mut self, select_start: usize, select_end: usize) {
|
||||
assert!(select_start <= self.state.text.len());
|
||||
assert!(select_end <= self.state.text.len());
|
||||
assert_eq!(self.state.text, self.text.get());
|
||||
|
||||
@@ -21,6 +21,7 @@ mod android;
|
||||
mod driver;
|
||||
#[cfg(target_os = "android")]
|
||||
pub use android::Editor;
|
||||
pub use driver::ParleyDriverWrapper;
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
mod parley;
|
||||
|
||||
@@ -57,19 +57,19 @@ impl Editor {
|
||||
pub fn focus(&self) {}
|
||||
pub fn unfocus(&self) {}
|
||||
|
||||
pub async fn on_text_prop_changed(&mut self) {
|
||||
pub fn on_text_prop_changed(&mut self) {
|
||||
// Get modified text property
|
||||
let txt = self.text.get();
|
||||
// Update Parley text buffer
|
||||
self.editor.set_text(&txt);
|
||||
// Refresh our layout
|
||||
self.refresh().await;
|
||||
self.refresh();
|
||||
}
|
||||
pub async fn on_buffer_changed(&mut self, atom: &mut PropertyAtomicGuard) {
|
||||
pub fn on_buffer_changed(&mut self, atom: &mut PropertyAtomicGuard) {
|
||||
self.text.set(atom, self.editor.raw_text());
|
||||
}
|
||||
|
||||
pub async fn refresh(&mut self) {
|
||||
pub fn refresh(&mut self) {
|
||||
let font_size = self.font_size.get();
|
||||
let text_color = self.text_color.get();
|
||||
let window_scale = self.window_scale.get();
|
||||
@@ -99,7 +99,7 @@ impl Editor {
|
||||
pub fn move_to_pos(&self, _pos: Point) {
|
||||
unimplemented!()
|
||||
}
|
||||
pub async fn select_word_at_point(&mut self, _pos: Point) {
|
||||
pub fn select_word_at_point(&mut self, _pos: Point) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@@ -109,9 +109,9 @@ impl Editor {
|
||||
cursor_pos
|
||||
}
|
||||
|
||||
pub async fn insert(&mut self, txt: &str, atom: &mut PropertyAtomicGuard) {
|
||||
pub fn insert(&mut self, txt: &str, atom: &mut PropertyAtomicGuard) {
|
||||
self.driver().insert_or_replace_selection(&txt);
|
||||
self.on_buffer_changed(atom).await;
|
||||
self.on_buffer_changed(atom);
|
||||
}
|
||||
|
||||
pub fn driver(&mut self) -> ParleyDriverWrapper {
|
||||
@@ -137,7 +137,7 @@ impl Editor {
|
||||
}
|
||||
/// Android uses byte indexes whereas parley has its own things. So this API is a compromise
|
||||
/// between them both.
|
||||
pub async fn set_selection(&mut self, select_start: usize, select_end: usize) {
|
||||
pub fn set_selection(&mut self, select_start: usize, select_end: usize) {
|
||||
self.driver().select_byte_range(select_start, select_end);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,14 +16,18 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::{cell::RefCell, ops::Range, sync::{Arc, LazyLock}};
|
||||
use parley::fontique::{Collection, CollectionOptions, SourceCache, SourceCacheOptions};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
ops::Range,
|
||||
sync::{Arc, LazyLock},
|
||||
};
|
||||
|
||||
use crate::{mesh::Color, util::spawn_thread};
|
||||
|
||||
pub mod atlas;
|
||||
mod editor;
|
||||
pub use editor::Editor;
|
||||
pub use editor::{Editor, ParleyDriverWrapper};
|
||||
mod render;
|
||||
pub use render::{render_layout, render_layout_with_opts, DebugRenderOptions};
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use async_lock::Mutex as AsyncMutex;
|
||||
use async_trait::async_trait;
|
||||
use atomic_float::AtomicF32;
|
||||
use parking_lot::Mutex as SyncMutex;
|
||||
@@ -27,8 +26,6 @@ use crate::{
|
||||
text::Editor,
|
||||
};
|
||||
|
||||
use super::EditorHandle;
|
||||
|
||||
//macro_rules! t { ($($arg:tt)*) => { trace!(target: "ui::edit::behave", $($arg)*); } }
|
||||
|
||||
pub enum BaseEditType {
|
||||
@@ -87,17 +84,12 @@ pub(super) struct MultiLine {
|
||||
pub padding: PropertyPtr,
|
||||
pub cursor_descent: PropertyFloat32,
|
||||
pub parent_rect: Arc<SyncMutex<Option<Rectangle>>>,
|
||||
pub editor: Arc<AsyncMutex<Option<Editor>>>,
|
||||
pub editor: Arc<SyncMutex<Editor>>,
|
||||
pub content_height: AtomicF32,
|
||||
pub scroll: Arc<AtomicF32>,
|
||||
}
|
||||
|
||||
impl MultiLine {
|
||||
/// Lazy-initializes the editor and returns a handle to it
|
||||
async fn lock_editor<'a>(&'a self) -> EditorHandle<'a> {
|
||||
EditorHandle { guard: self.editor.lock().await }
|
||||
}
|
||||
|
||||
fn bounded_height(&self, height: f32) -> f32 {
|
||||
height.clamp(self.min_height.get(), self.max_height.get())
|
||||
}
|
||||
@@ -112,7 +104,7 @@ impl MultiLine {
|
||||
/// Gets the real cursor pos within the rect.
|
||||
async fn get_cursor_pos(&self) -> Point {
|
||||
// This is the position within the content.
|
||||
let cursor_pos = self.lock_editor().await.get_cursor_pos();
|
||||
let cursor_pos = self.editor.lock().get_cursor_pos();
|
||||
// Apply the inner padding
|
||||
cursor_pos + self.inner_pos()
|
||||
}
|
||||
@@ -140,9 +132,9 @@ impl EditorBehavior for MultiLine {
|
||||
// Use the width to adjust the height calcs
|
||||
let rect_w = self.rect.get_width() - pad_left - pad_right;
|
||||
let content_height = {
|
||||
let mut editor = self.lock_editor().await;
|
||||
let mut editor = self.editor.lock();
|
||||
editor.set_width(rect_w);
|
||||
editor.refresh().await;
|
||||
editor.refresh();
|
||||
editor.height()
|
||||
};
|
||||
self.content_height.store(content_height, Ordering::Relaxed);
|
||||
@@ -242,24 +234,17 @@ pub(super) struct SingleLine {
|
||||
pub padding: PropertyPtr,
|
||||
pub cursor_width: PropertyFloat32,
|
||||
pub parent_rect: Arc<SyncMutex<Option<Rectangle>>>,
|
||||
pub editor: Arc<AsyncMutex<Option<Editor>>>,
|
||||
pub editor: Arc<SyncMutex<Editor>>,
|
||||
pub content_height: AtomicF32,
|
||||
pub scroll: Arc<AtomicF32>,
|
||||
}
|
||||
|
||||
impl SingleLine {
|
||||
/// Lazy-initializes the editor and returns a handle to it
|
||||
async fn lock_editor<'a>(&'a self) -> EditorHandle<'a> {
|
||||
EditorHandle { guard: self.editor.lock().await }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl EditorBehavior for SingleLine {
|
||||
async fn eval_rect(&self, atom: &mut PropertyAtomicGuard) {
|
||||
let content_height = {
|
||||
let mut editor = self.lock_editor().await;
|
||||
editor.refresh().await;
|
||||
let mut editor = self.editor.lock();
|
||||
editor.refresh();
|
||||
editor.height()
|
||||
};
|
||||
self.content_height.store(content_height, Ordering::Relaxed);
|
||||
@@ -283,7 +268,7 @@ impl EditorBehavior for SingleLine {
|
||||
let pad_left = self.padding.get_f32(3).unwrap();
|
||||
let scroll = self.scroll.load(Ordering::Relaxed);
|
||||
let rect_w = self.rect.get_width() - pad_right;
|
||||
let cursor_x0 = self.lock_editor().await.get_cursor_pos().x + pad_left;
|
||||
let cursor_x0 = self.editor.lock().get_cursor_pos().x + pad_left;
|
||||
let cursor_x1 = cursor_x0 + self.cursor_width.get();
|
||||
|
||||
if cursor_x0 < scroll {
|
||||
@@ -304,7 +289,7 @@ impl EditorBehavior for SingleLine {
|
||||
let pad_right = self.padding.get_f32(1).unwrap();
|
||||
let pad_left = self.padding.get_f32(3).unwrap();
|
||||
let rect_w = self.rect.get_width();
|
||||
let content_w = self.lock_editor().await.width() + self.cursor_width.get();
|
||||
let content_w = self.editor.lock().width() + self.cursor_width.get();
|
||||
(pad_left + pad_right + content_w - rect_w).max(0.)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use async_lock::Mutex as AsyncMutex;
|
||||
use async_trait::async_trait;
|
||||
use atomic_float::AtomicF32;
|
||||
use darkfi::system::msleep;
|
||||
@@ -179,23 +178,6 @@ impl std::fmt::Debug for Editor {
|
||||
}
|
||||
*/
|
||||
|
||||
struct EditorHandle<'a> {
|
||||
guard: async_lock::MutexGuard<'a, Option<Editor>>,
|
||||
}
|
||||
|
||||
impl<'a> Deref for EditorHandle<'a> {
|
||||
type Target = Editor;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.guard.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
impl<'a> DerefMut for EditorHandle<'a> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.guard.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub type BaseEditPtr = Arc<BaseEdit>;
|
||||
|
||||
pub struct BaseEdit {
|
||||
@@ -258,7 +240,7 @@ pub struct BaseEdit {
|
||||
parent_rect: Arc<SyncMutex<Option<Rectangle>>>,
|
||||
is_mouse_hover: AtomicBool,
|
||||
|
||||
editor: Arc<AsyncMutex<Option<Editor>>>,
|
||||
editor: Arc<SyncMutex<Editor>>,
|
||||
behave: Box<dyn EditorBehavior>,
|
||||
}
|
||||
|
||||
@@ -309,8 +291,16 @@ impl BaseEdit {
|
||||
let debug = PropertyBool::wrap(node_ref, Role::Internal, "debug", 0).unwrap();
|
||||
|
||||
let parent_rect = Arc::new(SyncMutex::new(None));
|
||||
let editor = Arc::new(AsyncMutex::new(None));
|
||||
let scroll = Arc::new(AtomicF32::new(0.));
|
||||
|
||||
let editor = Arc::new(SyncMutex::new(Editor::new(
|
||||
text.clone(),
|
||||
font_size.clone(),
|
||||
text_color.clone(),
|
||||
window_scale.clone(),
|
||||
lineheight.clone(),
|
||||
)));
|
||||
|
||||
let behave: Box<dyn EditorBehavior> = match edit_type {
|
||||
BaseEditType::SingleLine => Box::new(SingleLine {
|
||||
rect: rect.clone(),
|
||||
@@ -420,16 +410,11 @@ impl BaseEdit {
|
||||
/// Gets the real cursor pos within the rect.
|
||||
async fn get_cursor_pos(&self) -> Point {
|
||||
// This is the position within the content.
|
||||
let cursor_pos = self.lock_editor().await.get_cursor_pos();
|
||||
let cursor_pos = self.editor.lock().get_cursor_pos();
|
||||
// Apply the inner padding
|
||||
cursor_pos + self.behave.inner_pos()
|
||||
}
|
||||
|
||||
/// Lazy-initializes the editor and returns a handle to it
|
||||
async fn lock_editor<'a>(&'a self) -> EditorHandle<'a> {
|
||||
EditorHandle { guard: self.editor.lock().await }
|
||||
}
|
||||
|
||||
fn regen_cursor_mesh(&self) -> DrawMesh {
|
||||
let cursor_width = self.cursor_width.get();
|
||||
let cursor_ascent = self.cursor_ascent.get();
|
||||
@@ -516,7 +501,7 @@ impl BaseEdit {
|
||||
match key {
|
||||
'a' => {
|
||||
if action_mod {
|
||||
let mut editor = self.lock_editor().await;
|
||||
let mut editor = self.editor.lock();
|
||||
editor.driver().select_all();
|
||||
if let Some(seltext) = editor.selected_text() {
|
||||
self.select_text.clone().set_str(atom, Role::Internal, 0, seltext).unwrap();
|
||||
@@ -525,7 +510,7 @@ impl BaseEdit {
|
||||
}
|
||||
'c' => {
|
||||
if action_mod {
|
||||
let editor = self.lock_editor().await;
|
||||
let editor = self.editor.lock();
|
||||
if let Some(txt) = editor.selected_text() {
|
||||
miniquad::window::clipboard_set(&txt);
|
||||
}
|
||||
@@ -534,7 +519,7 @@ impl BaseEdit {
|
||||
'v' => {
|
||||
if action_mod {
|
||||
if let Some(txt) = miniquad::window::clipboard_get() {
|
||||
self.insert(&txt, atom).await;
|
||||
self.editor.lock().insert(&txt, atom);
|
||||
// Maybe insert should call this?
|
||||
self.behave.apply_cursor_scroll().await;
|
||||
}
|
||||
@@ -556,135 +541,132 @@ impl BaseEdit {
|
||||
) -> bool {
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let action_mod = mods.ctrl;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let action_mod = mods.logo;
|
||||
|
||||
t!("handle_key({:?}, {:?}) action_mod={action_mod}", key, mods);
|
||||
{
|
||||
let mut editor = self.editor.lock();
|
||||
match key {
|
||||
KeyCode::Left => {
|
||||
if action_mod {
|
||||
if mods.shift {
|
||||
editor.driver().select_word_left();
|
||||
} else {
|
||||
editor.driver().move_word_left();
|
||||
}
|
||||
} else if mods.shift {
|
||||
editor.driver().select_left();
|
||||
} else {
|
||||
editor.driver().move_left();
|
||||
}
|
||||
}
|
||||
KeyCode::Right => {
|
||||
if action_mod {
|
||||
if mods.shift {
|
||||
editor.driver().select_word_right();
|
||||
} else {
|
||||
editor.driver().move_word_right();
|
||||
}
|
||||
} else if mods.shift {
|
||||
editor.driver().select_right();
|
||||
} else {
|
||||
editor.driver().move_right();
|
||||
}
|
||||
}
|
||||
KeyCode::Up => {
|
||||
if mods.shift {
|
||||
editor.driver().select_up();
|
||||
} else {
|
||||
editor.driver().move_up();
|
||||
}
|
||||
}
|
||||
KeyCode::Down => {
|
||||
if mods.shift {
|
||||
editor.driver().select_down();
|
||||
} else {
|
||||
editor.driver().move_down();
|
||||
}
|
||||
}
|
||||
KeyCode::Enter | KeyCode::KpEnter => {
|
||||
if mods.shift {
|
||||
if self.behave.allow_endl() {
|
||||
editor.driver().insert_or_replace_selection("\n");
|
||||
editor.on_buffer_changed(atom);
|
||||
}
|
||||
} else {
|
||||
//let node = self.node.upgrade().unwrap();
|
||||
//node.trigger("enter_pressed", vec![]).await.unwrap();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
KeyCode::Delete => {
|
||||
if action_mod {
|
||||
editor.driver().delete_word();
|
||||
} else {
|
||||
editor.driver().delete();
|
||||
}
|
||||
editor.on_buffer_changed(atom);
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
if action_mod {
|
||||
editor.driver().backdelete_word();
|
||||
} else {
|
||||
editor.driver().backdelete();
|
||||
}
|
||||
editor.on_buffer_changed(atom);
|
||||
}
|
||||
KeyCode::Home => {
|
||||
if action_mod {
|
||||
if mods.shift {
|
||||
editor.driver().select_to_text_start();
|
||||
} else {
|
||||
editor.driver().move_to_text_start();
|
||||
}
|
||||
} else if mods.shift {
|
||||
editor.driver().select_to_line_start();
|
||||
} else {
|
||||
editor.driver().move_to_line_start();
|
||||
}
|
||||
}
|
||||
KeyCode::End => {
|
||||
if action_mod {
|
||||
if mods.shift {
|
||||
editor.driver().select_to_text_end();
|
||||
} else {
|
||||
editor.driver().move_to_text_end();
|
||||
}
|
||||
} else if mods.shift {
|
||||
editor.driver().select_to_line_end();
|
||||
} else {
|
||||
editor.driver().move_to_line_end();
|
||||
}
|
||||
}
|
||||
_ => return false,
|
||||
}
|
||||
|
||||
let mut editor = self.lock_editor().await;
|
||||
|
||||
match key {
|
||||
KeyCode::Left => {
|
||||
if action_mod {
|
||||
if mods.shift {
|
||||
editor.driver().select_word_left();
|
||||
} else {
|
||||
editor.driver().move_word_left();
|
||||
}
|
||||
} else if mods.shift {
|
||||
editor.driver().select_left();
|
||||
} else {
|
||||
editor.driver().move_left();
|
||||
}
|
||||
if let Some(seltext) = editor.selected_text() {
|
||||
self.select_text.clone().set_str(atom, Role::Internal, 0, seltext).unwrap();
|
||||
} else {
|
||||
self.select_text.clone().set_null(atom, Role::Internal, 0).unwrap();
|
||||
}
|
||||
KeyCode::Right => {
|
||||
if action_mod {
|
||||
if mods.shift {
|
||||
editor.driver().select_word_right();
|
||||
} else {
|
||||
editor.driver().move_word_right();
|
||||
}
|
||||
} else if mods.shift {
|
||||
editor.driver().select_right();
|
||||
} else {
|
||||
editor.driver().move_right();
|
||||
}
|
||||
}
|
||||
KeyCode::Up => {
|
||||
if mods.shift {
|
||||
editor.driver().select_up();
|
||||
} else {
|
||||
editor.driver().move_up();
|
||||
}
|
||||
}
|
||||
KeyCode::Down => {
|
||||
if mods.shift {
|
||||
editor.driver().select_down();
|
||||
} else {
|
||||
editor.driver().move_down();
|
||||
}
|
||||
}
|
||||
KeyCode::Enter | KeyCode::KpEnter => {
|
||||
if mods.shift {
|
||||
if self.behave.allow_endl() {
|
||||
editor.driver().insert_or_replace_selection("\n");
|
||||
editor.on_buffer_changed(atom).await;
|
||||
}
|
||||
} else {
|
||||
//let node = self.node.upgrade().unwrap();
|
||||
//node.trigger("enter_pressed", vec![]).await.unwrap();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
KeyCode::Delete => {
|
||||
if action_mod {
|
||||
editor.driver().delete_word();
|
||||
} else {
|
||||
editor.driver().delete();
|
||||
}
|
||||
editor.on_buffer_changed(atom).await;
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
if action_mod {
|
||||
editor.driver().backdelete_word();
|
||||
} else {
|
||||
editor.driver().backdelete();
|
||||
}
|
||||
editor.on_buffer_changed(atom).await;
|
||||
}
|
||||
KeyCode::Home => {
|
||||
if action_mod {
|
||||
if mods.shift {
|
||||
editor.driver().select_to_text_start();
|
||||
} else {
|
||||
editor.driver().move_to_text_start();
|
||||
}
|
||||
} else if mods.shift {
|
||||
editor.driver().select_to_line_start();
|
||||
} else {
|
||||
editor.driver().move_to_line_start();
|
||||
}
|
||||
}
|
||||
KeyCode::End => {
|
||||
if action_mod {
|
||||
if mods.shift {
|
||||
editor.driver().select_to_text_end();
|
||||
} else {
|
||||
editor.driver().move_to_text_end();
|
||||
}
|
||||
} else if mods.shift {
|
||||
editor.driver().select_to_line_end();
|
||||
} else {
|
||||
editor.driver().move_to_line_end();
|
||||
}
|
||||
}
|
||||
_ => return false,
|
||||
}
|
||||
|
||||
if let Some(seltext) = editor.selected_text() {
|
||||
self.select_text.clone().set_str(atom, Role::Internal, 0, seltext).unwrap();
|
||||
} else {
|
||||
self.select_text.clone().set_null(atom, Role::Internal, 0).unwrap();
|
||||
}
|
||||
|
||||
drop(editor);
|
||||
|
||||
self.eval_rect().await;
|
||||
self.behave.apply_cursor_scroll().await;
|
||||
self.pause_blinking();
|
||||
self.redraw(atom).await;
|
||||
|
||||
return true
|
||||
true
|
||||
}
|
||||
|
||||
/// This will select the entire word rather than move the cursor to that location
|
||||
async fn start_touch_select(&self, touch_pos: Point, atom: &mut PropertyAtomicGuard) {
|
||||
t!("start_touch_select({touch_pos:?})");
|
||||
|
||||
let mut editor = self.lock_editor().await;
|
||||
editor.select_word_at_point(touch_pos).await;
|
||||
editor.refresh().await;
|
||||
let mut editor = self.editor.lock();
|
||||
editor.select_word_at_point(touch_pos);
|
||||
editor.refresh();
|
||||
|
||||
let seltext = editor.selected_text().unwrap();
|
||||
d!("Selected {seltext:?} from {touch_pos:?}");
|
||||
@@ -717,7 +699,7 @@ impl BaseEdit {
|
||||
true
|
||||
}
|
||||
|
||||
async fn get_select_handles(&self, editor: &Editor) -> Option<(Point, Point)> {
|
||||
fn get_select_handles(&self, editor: &Editor) -> Option<(Point, Point)> {
|
||||
let layout = editor.layout();
|
||||
|
||||
let sel = editor.selection(1);
|
||||
@@ -732,10 +714,8 @@ impl BaseEdit {
|
||||
}
|
||||
|
||||
async fn try_handle_drag(&self, mut touch_pos: Point) -> bool {
|
||||
let editor = self.lock_editor().await;
|
||||
let Some((mut first, mut last)) = self.get_select_handles(&editor).await else {
|
||||
return false
|
||||
};
|
||||
let editor = self.editor.lock();
|
||||
let Some((mut first, mut last)) = self.get_select_handles(&editor) else { return false };
|
||||
|
||||
self.abs_to_local(&mut touch_pos);
|
||||
t!("localize touch_pos = {touch_pos:?}");
|
||||
@@ -878,9 +858,9 @@ impl BaseEdit {
|
||||
async fn touch_set_cursor_pos(&self, atom: &mut PropertyAtomicGuard, touch_pos: Point) {
|
||||
t!("touch_set_cursor_pos({touch_pos:?})");
|
||||
|
||||
let mut editor = self.lock_editor().await;
|
||||
let mut editor = self.editor.lock();
|
||||
editor.move_to_pos(touch_pos);
|
||||
editor.refresh().await;
|
||||
editor.refresh();
|
||||
drop(editor);
|
||||
|
||||
self.pause_blinking();
|
||||
@@ -926,7 +906,7 @@ impl BaseEdit {
|
||||
}
|
||||
|
||||
let seltext = {
|
||||
let mut editor = self.lock_editor().await;
|
||||
let mut editor = self.editor.lock();
|
||||
|
||||
// The below lines rely on parley driver which android does not use
|
||||
//let mut txt_ctx = text::TEXT_CTX.get().await;
|
||||
@@ -970,8 +950,8 @@ impl BaseEdit {
|
||||
assert!(start < end);
|
||||
|
||||
//t!("handle_select(): set_selection({start}, {end})");
|
||||
editor.set_selection(start, end).await;
|
||||
editor.refresh().await;
|
||||
editor.set_selection(start, end);
|
||||
editor.refresh();
|
||||
|
||||
editor.selected_text()
|
||||
};
|
||||
@@ -1096,7 +1076,7 @@ impl BaseEdit {
|
||||
async fn regen_txt_mesh(&self) -> Vec<DrawInstruction> {
|
||||
let mut instrs = vec![DrawInstruction::Move(self.behave.inner_pos())];
|
||||
|
||||
let editor = self.lock_editor().await;
|
||||
let editor = self.editor.lock();
|
||||
let layout = editor.layout();
|
||||
|
||||
let mut render_instrs =
|
||||
@@ -1109,7 +1089,7 @@ impl BaseEdit {
|
||||
async fn regen_select_mesh(&self) -> Vec<DrawInstruction> {
|
||||
let mut instrs = vec![DrawInstruction::Move(self.behave.inner_pos())];
|
||||
|
||||
let editor = self.lock_editor().await;
|
||||
let editor = self.editor.lock();
|
||||
let layout = editor.layout();
|
||||
|
||||
let sel = editor.selection(1);
|
||||
@@ -1131,8 +1111,8 @@ impl BaseEdit {
|
||||
//t!("regen_phone_select_handle_mesh() [DISABLED]");
|
||||
return vec![]
|
||||
}
|
||||
let editor = self.lock_editor().await;
|
||||
let (first, last) = self.get_select_handles(&editor).await.unwrap();
|
||||
let editor = self.editor.lock();
|
||||
let (first, last) = self.get_select_handles(&editor).unwrap();
|
||||
|
||||
let sel = editor.selection(1);
|
||||
assert!(!sel.is_collapsed());
|
||||
@@ -1214,11 +1194,6 @@ impl BaseEdit {
|
||||
}
|
||||
}
|
||||
|
||||
async fn insert(&self, txt: &str, atom: &mut PropertyAtomicGuard) {
|
||||
let mut editor = self.lock_editor().await;
|
||||
editor.insert(txt, atom).await;
|
||||
}
|
||||
|
||||
async fn process_insert_text_method(me: &Weak<Self>, sub: &MethodCallSub) -> bool {
|
||||
let Ok(method_call) = sub.receive().await else {
|
||||
debug!(target: "ui::chatedit", "Event relayer closed");
|
||||
@@ -1246,7 +1221,7 @@ impl BaseEdit {
|
||||
|
||||
let atom =
|
||||
&mut self_.render_api.make_guard(gfxtag!("BaseEdit::process_insert_text_method"));
|
||||
self_.insert(&text, atom).await;
|
||||
self_.editor.lock().insert(&text, atom);
|
||||
self_.eval_rect().await;
|
||||
self_.redraw(atom).await;
|
||||
true
|
||||
@@ -1267,8 +1242,7 @@ impl BaseEdit {
|
||||
panic!("self destroyed before insert_text_method_task was stopped!");
|
||||
};
|
||||
|
||||
let mut editor = self_.lock_editor().await;
|
||||
editor.focus();
|
||||
self_.editor.lock().focus();
|
||||
true
|
||||
}
|
||||
async fn process_unfocus_method(me: &Weak<Self>, sub: &MethodCallSub) -> bool {
|
||||
@@ -1286,8 +1260,7 @@ impl BaseEdit {
|
||||
panic!("self destroyed before insert_text_method_task was stopped!");
|
||||
};
|
||||
|
||||
let mut editor = self_.lock_editor().await;
|
||||
editor.unfocus();
|
||||
self_.editor.lock().unfocus();
|
||||
true
|
||||
}
|
||||
|
||||
@@ -1300,7 +1273,7 @@ impl BaseEdit {
|
||||
t!("handle_android_event({state:?})");
|
||||
let atom = &mut self.render_api.make_guard(gfxtag!("BaseEdit::handle_android_event"));
|
||||
|
||||
let mut editor = self.lock_editor().await;
|
||||
let mut editor = self.editor.lock();
|
||||
// Diff old and new state so we know what changed
|
||||
let is_text_changed = editor.state.text != state.text;
|
||||
let is_select_changed = editor.state.select != state.select;
|
||||
@@ -1357,22 +1330,7 @@ impl UIObject for BaseEdit {
|
||||
self.priority.get()
|
||||
}
|
||||
|
||||
fn init(&self) {
|
||||
let mut guard = self.editor.lock_blocking();
|
||||
assert!(guard.is_none());
|
||||
let editor = Editor::new(
|
||||
self.text.clone(),
|
||||
self.font_size.clone(),
|
||||
self.text_color.clone(),
|
||||
self.window_scale.clone(),
|
||||
self.lineheight.clone(),
|
||||
);
|
||||
// For Android you can do this:
|
||||
//let atom = &mut PropertyAtomicGuard::none();
|
||||
//self.text.set(atom, "the quick brown fox jumped over the");
|
||||
//smol::block_on(editor.on_text_prop_changed());
|
||||
*guard = Some(editor);
|
||||
}
|
||||
fn init(&self) {}
|
||||
|
||||
async fn start(self: Arc<Self>, ex: ExecutorPtr) {
|
||||
let me = Arc::downgrade(&self);
|
||||
@@ -1414,7 +1372,7 @@ impl UIObject for BaseEdit {
|
||||
self_.redraw(atom).await;
|
||||
}
|
||||
async fn set_text(self_: Arc<BaseEdit>, batch: BatchGuardPtr) {
|
||||
self_.lock_editor().await.on_text_prop_changed().await;
|
||||
self_.editor.lock().on_text_prop_changed();
|
||||
let atom = &mut batch.spawn();
|
||||
self_.eval_rect().await;
|
||||
self_.redraw(atom).await;
|
||||
@@ -1549,7 +1507,6 @@ impl UIObject for BaseEdit {
|
||||
*self.parent_rect.lock() = None;
|
||||
self.key_repeat.lock().clear();
|
||||
*self.cursor_mesh.lock() = None;
|
||||
*self.editor.lock_blocking() = None;
|
||||
}
|
||||
|
||||
#[instrument(target = "ui::edit")]
|
||||
@@ -1598,7 +1555,7 @@ impl UIObject for BaseEdit {
|
||||
|
||||
t!("Key {:?} has {} actions", key, actions);
|
||||
let key_str = key.to_string().repeat(actions as usize);
|
||||
self.insert(&key_str, atom).await;
|
||||
self.editor.lock().insert(&key_str, atom);
|
||||
self.eval_rect().await;
|
||||
self.behave.apply_cursor_scroll().await;
|
||||
self.redraw(atom).await;
|
||||
@@ -1672,10 +1629,7 @@ impl UIObject for BaseEdit {
|
||||
// Move mouse pos within this widget
|
||||
self.abs_to_local(&mut mouse_pos);
|
||||
|
||||
{
|
||||
let mut editor = self.lock_editor().await;
|
||||
editor.driver().move_to_point(mouse_pos.x, mouse_pos.y);
|
||||
}
|
||||
self.editor.lock().driver().move_to_point(mouse_pos.x, mouse_pos.y);
|
||||
|
||||
if !self.select_text.is_null(0).unwrap() {
|
||||
self.select_text.clone().set_null(atom, Role::Internal, 0).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user