mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-08 22:28:12 -05:00
app/editor: add ParleyDriverWrapper which hugely simplifies driver access pattern
This commit is contained in:
@@ -16,6 +16,9 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::cmp::{max, min};
|
||||
|
||||
use super::driver::ParleyDriverWrapper;
|
||||
use crate::{
|
||||
android::{
|
||||
self,
|
||||
@@ -26,7 +29,6 @@ use crate::{
|
||||
prop::{PropertyAtomicGuard, PropertyColor, PropertyFloat32, PropertyStr},
|
||||
text,
|
||||
};
|
||||
use std::cmp::{max, min};
|
||||
|
||||
macro_rules! t { ($($arg:tt)*) => { trace!(target: "text::editor::android", $($arg)*); } }
|
||||
|
||||
@@ -172,11 +174,8 @@ impl Editor {
|
||||
self.on_buffer_changed(atom).await;
|
||||
}
|
||||
|
||||
pub fn driver<'a>(
|
||||
&'a mut self,
|
||||
_layout_ctx: &'a mut parley::LayoutContext<Color>,
|
||||
) -> Option<parley::PlainEditorDriver<'a, Color>> {
|
||||
None
|
||||
pub fn driver(&mut self) -> ParleyDriverWrapper {
|
||||
ParleyDriverWrapper::new(&mut self.layout)
|
||||
}
|
||||
|
||||
pub fn set_width(&mut self, w: f32) {
|
||||
|
||||
282
bin/app/src/text/editor/driver.rs
Normal file
282
bin/app/src/text/editor/driver.rs
Normal file
@@ -0,0 +1,282 @@
|
||||
/* This file is part of DarkFi (https://dark.fi)
|
||||
*
|
||||
* Copyright (C) 2020-2026 Dyne.org foundation
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
use crate::{mesh::Color, text};
|
||||
|
||||
pub struct ParleyDriverWrapper<'a> {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
editor: &'a mut parley::PlainEditor<Color>,
|
||||
}
|
||||
|
||||
impl<'a> ParleyDriverWrapper<'a> {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub fn new(editor: &'a mut parley::PlainEditor<Color>) -> Self {
|
||||
Self { editor }
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub fn new(_layout: &mut parley::Layout<Color>) -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn with_driver<F, R>(&mut self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut parley::PlainEditorDriver<'_, Color>) -> R,
|
||||
{
|
||||
let mut font_ctx = text::GLOBAL_FONT_CTX.clone();
|
||||
text::THREAD_LAYOUT_CTX.with(|layout_ctx| {
|
||||
let mut layout_ctx = layout_ctx.borrow_mut();
|
||||
let mut driver = self.editor.driver(&mut font_ctx, &mut layout_ctx);
|
||||
f(&mut driver)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn select_all(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.select_all());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn select_word_left(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.select_word_left());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn move_word_left(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.move_word_left());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn select_left(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.select_left());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn move_left(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.move_left());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn select_word_right(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.select_word_right());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn move_word_right(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.move_word_right());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn select_right(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.select_right());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn move_right(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.move_right());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn select_up(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.select_up());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn move_up(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.move_up());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn select_down(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.select_down());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn move_down(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.move_down());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn insert_or_replace_selection(&mut self, text: &str) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.insert_or_replace_selection(text));
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn delete(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.delete());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn delete_word(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.delete_word());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn backdelete(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.backdelete());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn backdelete_word(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.backdelete_word());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn select_to_text_start(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.select_to_text_start());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn move_to_text_start(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.move_to_text_start());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn select_to_line_start(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.select_to_line_start());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn move_to_line_start(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.move_to_line_start());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn select_to_text_end(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.select_to_text_end());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn move_to_text_end(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.move_to_text_end());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn select_to_line_end(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.select_to_line_end());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn move_to_line_end(&mut self) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.move_to_line_end());
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn move_to_point(&mut self, x: f32, y: f32) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.move_to_point(x, y));
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn extend_selection_to_point(&mut self, x: f32, y: f32) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.extend_selection_to_point(x, y));
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn select_byte_range(&mut self, start: usize, end: usize) {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
self.with_driver(|drv| drv.select_byte_range(start, end));
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
mod android;
|
||||
mod driver;
|
||||
#[cfg(target_os = "android")]
|
||||
pub use android::Editor;
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ use crate::{
|
||||
text::{self, FONT_STACK},
|
||||
};
|
||||
|
||||
use super::driver::ParleyDriverWrapper;
|
||||
|
||||
pub struct Editor {
|
||||
editor: parley::PlainEditor<Color>,
|
||||
|
||||
@@ -108,20 +110,12 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub async fn insert(&mut self, txt: &str, atom: &mut PropertyAtomicGuard) {
|
||||
text::THREAD_LAYOUT_CTX.with(|layout_ctx| {
|
||||
let mut layout_ctx = layout_ctx.borrow_mut();
|
||||
let mut drv = self.driver(&mut layout_ctx);
|
||||
drv.insert_or_replace_selection(&txt);
|
||||
self.on_buffer_changed(atom).await;
|
||||
});
|
||||
self.driver().insert_or_replace_selection(&txt);
|
||||
self.on_buffer_changed(atom).await;
|
||||
}
|
||||
|
||||
pub fn driver<'a>(
|
||||
&'a mut self,
|
||||
layout_ctx: &'a mut parley::LayoutContext<Color>,
|
||||
) -> Option<parley::PlainEditorDriver<'a, Color>> {
|
||||
let mut font_ctx = text::GLOBAL_FONT_CTX.clone();
|
||||
Some(self.editor.driver(&mut font_ctx, layout_ctx))
|
||||
pub fn driver(&mut self) -> ParleyDriverWrapper {
|
||||
ParleyDriverWrapper::new(&mut self.editor)
|
||||
}
|
||||
|
||||
pub fn set_width(&mut self, w: f32) {
|
||||
@@ -144,11 +138,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) {
|
||||
text::THREAD_LAYOUT_CTX.with(|layout_ctx| {
|
||||
let mut layout_ctx = layout_ctx.borrow_mut();
|
||||
let mut drv = self.driver(&mut layout_ctx);
|
||||
drv.select_byte_range(select_start, select_end);
|
||||
});
|
||||
self.driver().select_byte_range(select_start, select_end);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
||||
@@ -16,14 +16,8 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
ops::Range,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use fontique::{Collection, CollectionOptions, SourceCache, SourceCacheOptions};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::{cell::RefCell, ops::Range, sync::{Arc, LazyLock}};
|
||||
use parley::fontique::{Collection, CollectionOptions, SourceCache, SourceCacheOptions};
|
||||
|
||||
use crate::{mesh::Color, util::spawn_thread};
|
||||
|
||||
@@ -34,36 +28,25 @@ mod render;
|
||||
pub use render::{render_layout, render_layout_with_opts, DebugRenderOptions};
|
||||
|
||||
// Global shared FontContext (thread-safe via internal Arc<Mutex<>>)
|
||||
pub static GLOBAL_FONT_CTX: Lazy<parley::FontContext> = Lazy::new(|| {
|
||||
let collection = Collection::new(CollectionOptions {
|
||||
shared: true,
|
||||
system_fonts: false,
|
||||
});
|
||||
pub static GLOBAL_FONT_CTX: LazyLock<parley::FontContext> = LazyLock::new(|| {
|
||||
let collection = Collection::new(CollectionOptions { shared: true, system_fonts: false });
|
||||
|
||||
let source_cache = SourceCache::new(SourceCacheOptions {
|
||||
shared: true,
|
||||
});
|
||||
let source_cache = SourceCache::new(SourceCacheOptions { shared: true });
|
||||
|
||||
let mut font_ctx = parley::FontContext { collection, source_cache };
|
||||
|
||||
let font_data = include_bytes!("../../ibm-plex-mono-regular.otf") as &[u8];
|
||||
font_ctx.collection.register_fonts(
|
||||
peniko::Blob::new(Arc::new(font_data)),
|
||||
None
|
||||
);
|
||||
font_ctx.collection.register_fonts(peniko::Blob::new(Arc::new(font_data)), None);
|
||||
|
||||
let font_data = include_bytes!("../../NotoColorEmoji.ttf") as &[u8];
|
||||
font_ctx.collection.register_fonts(
|
||||
peniko::Blob::new(Arc::new(font_data)),
|
||||
None
|
||||
);
|
||||
font_ctx.collection.register_fonts(peniko::Blob::new(Arc::new(font_data)), None);
|
||||
|
||||
font_ctx
|
||||
});
|
||||
|
||||
// Thread-local LayoutContext
|
||||
thread_local! {
|
||||
pub static THREAD_LAYOUT_CTX: RefCell<parley::LayoutContext<'static, Color>> =
|
||||
pub static THREAD_LAYOUT_CTX: RefCell<parley::LayoutContext<Color>> =
|
||||
RefCell::new(parley::LayoutContext::new());
|
||||
}
|
||||
|
||||
@@ -83,16 +66,7 @@ pub fn make_layout(
|
||||
width: Option<f32>,
|
||||
underlines: &[Range<usize>],
|
||||
) -> parley::Layout<Color> {
|
||||
make_layout2(
|
||||
text,
|
||||
text_color,
|
||||
font_size,
|
||||
lineheight,
|
||||
window_scale,
|
||||
width,
|
||||
underlines,
|
||||
&[],
|
||||
)
|
||||
make_layout2(text, text_color, font_size, lineheight, window_scale, width, underlines, &[])
|
||||
}
|
||||
|
||||
pub fn make_layout2(
|
||||
@@ -109,8 +83,7 @@ pub fn make_layout2(
|
||||
let mut layout_ctx = layout_ctx.borrow_mut();
|
||||
let mut font_ctx = GLOBAL_FONT_CTX.clone();
|
||||
|
||||
let mut builder =
|
||||
layout_ctx.ranged_builder(&mut font_ctx, text, window_scale, false);
|
||||
let mut builder = layout_ctx.ranged_builder(&mut font_ctx, text, window_scale, false);
|
||||
builder.push_default(parley::LineHeight::FontSizeRelative(lineheight));
|
||||
builder.push_default(parley::StyleProperty::FontSize(font_size));
|
||||
builder.push_default(parley::StyleProperty::FontStack(parley::FontStack::List(
|
||||
|
||||
@@ -184,13 +184,7 @@ impl PrivMessage {
|
||||
&[],
|
||||
);
|
||||
|
||||
self.cache_txt_layout(
|
||||
clip,
|
||||
line_height,
|
||||
timestamp_width,
|
||||
nick_colors,
|
||||
text_color,
|
||||
);
|
||||
self.cache_txt_layout(clip, line_height, timestamp_width, nick_colors, text_color);
|
||||
|
||||
let mut all_instrs = vec![];
|
||||
|
||||
@@ -652,13 +646,7 @@ impl Message {
|
||||
) {
|
||||
match self {
|
||||
Self::Priv(m) => {
|
||||
m.cache_txt_layout(
|
||||
clip,
|
||||
line_height,
|
||||
timestamp_width,
|
||||
nick_colors,
|
||||
text_color,
|
||||
);
|
||||
m.cache_txt_layout(clip, line_height, timestamp_width, nick_colors, text_color);
|
||||
}
|
||||
Self::Date(_) => {}
|
||||
Self::File(_) => {}
|
||||
@@ -859,13 +847,7 @@ impl MessageBuffer {
|
||||
height += msg_spacing;
|
||||
}
|
||||
|
||||
msg.cache_txt_layout(
|
||||
&rect,
|
||||
line_height,
|
||||
timestamp_width,
|
||||
&nick_colors,
|
||||
text_color,
|
||||
);
|
||||
msg.cache_txt_layout(&rect, line_height, timestamp_width, &nick_colors, text_color);
|
||||
|
||||
height += msg.height(line_height);
|
||||
}
|
||||
@@ -924,13 +906,7 @@ impl MessageBuffer {
|
||||
text,
|
||||
);
|
||||
|
||||
msg.cache_txt_layout(
|
||||
&rect,
|
||||
line_height,
|
||||
timestamp_width,
|
||||
&nick_colors,
|
||||
text_color,
|
||||
);
|
||||
msg.cache_txt_layout(&rect, line_height, timestamp_width, &nick_colors, text_color);
|
||||
|
||||
if self.msgs.is_empty() {
|
||||
self.msgs.push(msg);
|
||||
@@ -994,13 +970,7 @@ impl MessageBuffer {
|
||||
text,
|
||||
);
|
||||
|
||||
msg.cache_txt_layout(
|
||||
rect,
|
||||
line_height,
|
||||
timestamp_width,
|
||||
&nick_colors,
|
||||
text_color,
|
||||
);
|
||||
msg.cache_txt_layout(rect, line_height, timestamp_width, &nick_colors, text_color);
|
||||
|
||||
let msg_height = msg.height(self.line_height.get());
|
||||
self.msgs.push(msg);
|
||||
|
||||
@@ -40,7 +40,7 @@ use tracing::instrument;
|
||||
use crate::android::textinput::AndroidTextInputState;
|
||||
use crate::{
|
||||
gfx::{gfxtag, DrawCall, DrawInstruction, DrawMesh, Point, Rectangle, RenderApi, Vertex},
|
||||
mesh::MeshBuilder,
|
||||
mesh::{Color, MeshBuilder},
|
||||
prop::{
|
||||
BatchGuardId, BatchGuardPtr, PropertyAtomicGuard, PropertyBool, PropertyColor,
|
||||
PropertyFloat32, PropertyPtr, PropertyRect, PropertyStr, PropertyUint32, Role,
|
||||
@@ -501,7 +501,6 @@ impl BaseEdit {
|
||||
|
||||
async fn handle_shortcut(
|
||||
&self,
|
||||
layout_ctx: &mut parley::LayoutContext<Color>,
|
||||
key: char,
|
||||
mods: &KeyMods,
|
||||
atom: &mut PropertyAtomicGuard,
|
||||
@@ -518,9 +517,7 @@ impl BaseEdit {
|
||||
'a' => {
|
||||
if action_mod {
|
||||
let mut editor = self.lock_editor().await;
|
||||
let mut drv = editor.driver(layout_ctx);
|
||||
|
||||
drv.select_all();
|
||||
editor.driver().select_all();
|
||||
if let Some(seltext) = editor.selected_text() {
|
||||
self.select_text.clone().set_str(atom, Role::Internal, 0, seltext).unwrap();
|
||||
}
|
||||
@@ -553,7 +550,6 @@ impl BaseEdit {
|
||||
|
||||
async fn handle_key(
|
||||
&self,
|
||||
layout_ctx: &mut parley::LayoutContext<Color>,
|
||||
key: &KeyCode,
|
||||
mods: &KeyMods,
|
||||
atom: &mut PropertyAtomicGuard,
|
||||
@@ -567,53 +563,52 @@ impl BaseEdit {
|
||||
t!("handle_key({:?}, {:?}) action_mod={action_mod}", key, mods);
|
||||
|
||||
let mut editor = self.lock_editor().await;
|
||||
let mut drv = editor.driver(layout_ctx);
|
||||
|
||||
match key {
|
||||
KeyCode::Left => {
|
||||
if action_mod {
|
||||
if mods.shift {
|
||||
drv.select_word_left();
|
||||
editor.driver().select_word_left();
|
||||
} else {
|
||||
drv.move_word_left();
|
||||
editor.driver().move_word_left();
|
||||
}
|
||||
} else if mods.shift {
|
||||
drv.select_left();
|
||||
editor.driver().select_left();
|
||||
} else {
|
||||
drv.move_left();
|
||||
editor.driver().move_left();
|
||||
}
|
||||
}
|
||||
KeyCode::Right => {
|
||||
if action_mod {
|
||||
if mods.shift {
|
||||
drv.select_word_right();
|
||||
editor.driver().select_word_right();
|
||||
} else {
|
||||
drv.move_word_right();
|
||||
editor.driver().move_word_right();
|
||||
}
|
||||
} else if mods.shift {
|
||||
drv.select_right();
|
||||
editor.driver().select_right();
|
||||
} else {
|
||||
drv.move_right();
|
||||
editor.driver().move_right();
|
||||
}
|
||||
}
|
||||
KeyCode::Up => {
|
||||
if mods.shift {
|
||||
drv.select_up();
|
||||
editor.driver().select_up();
|
||||
} else {
|
||||
drv.move_up();
|
||||
editor.driver().move_up();
|
||||
}
|
||||
}
|
||||
KeyCode::Down => {
|
||||
if mods.shift {
|
||||
drv.select_down();
|
||||
editor.driver().select_down();
|
||||
} else {
|
||||
drv.move_down();
|
||||
editor.driver().move_down();
|
||||
}
|
||||
}
|
||||
KeyCode::Enter | KeyCode::KpEnter => {
|
||||
if mods.shift {
|
||||
if self.behave.allow_endl() {
|
||||
drv.insert_or_replace_selection("\n");
|
||||
editor.driver().insert_or_replace_selection("\n");
|
||||
editor.on_buffer_changed(atom).await;
|
||||
}
|
||||
} else {
|
||||
@@ -624,44 +619,44 @@ impl BaseEdit {
|
||||
}
|
||||
KeyCode::Delete => {
|
||||
if action_mod {
|
||||
drv.delete_word();
|
||||
editor.driver().delete_word();
|
||||
} else {
|
||||
drv.delete();
|
||||
editor.driver().delete();
|
||||
}
|
||||
editor.on_buffer_changed(atom).await;
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
if action_mod {
|
||||
drv.backdelete_word();
|
||||
editor.driver().backdelete_word();
|
||||
} else {
|
||||
drv.backdelete();
|
||||
editor.driver().backdelete();
|
||||
}
|
||||
editor.on_buffer_changed(atom).await;
|
||||
}
|
||||
KeyCode::Home => {
|
||||
if action_mod {
|
||||
if mods.shift {
|
||||
drv.select_to_text_start();
|
||||
editor.driver().select_to_text_start();
|
||||
} else {
|
||||
drv.move_to_text_start();
|
||||
editor.driver().move_to_text_start();
|
||||
}
|
||||
} else if mods.shift {
|
||||
drv.select_to_line_start();
|
||||
editor.driver().select_to_line_start();
|
||||
} else {
|
||||
drv.move_to_line_start();
|
||||
editor.driver().move_to_line_start();
|
||||
}
|
||||
}
|
||||
KeyCode::End => {
|
||||
if action_mod {
|
||||
if mods.shift {
|
||||
drv.select_to_text_end();
|
||||
editor.driver().select_to_text_end();
|
||||
} else {
|
||||
drv.move_to_text_end();
|
||||
editor.driver().move_to_text_end();
|
||||
}
|
||||
} else if mods.shift {
|
||||
drv.select_to_line_end();
|
||||
editor.driver().select_to_line_end();
|
||||
} else {
|
||||
drv.move_to_line_end();
|
||||
editor.driver().move_to_line_end();
|
||||
}
|
||||
}
|
||||
_ => return false,
|
||||
@@ -674,7 +669,6 @@ impl BaseEdit {
|
||||
}
|
||||
|
||||
drop(editor);
|
||||
drop(txt_ctx);
|
||||
|
||||
self.eval_rect().await;
|
||||
self.behave.apply_cursor_scroll().await;
|
||||
@@ -1594,10 +1588,7 @@ impl UIObject for BaseEdit {
|
||||
if repeat {
|
||||
return false
|
||||
}
|
||||
return text::THREAD_LAYOUT_CTX.with(|layout_ctx| {
|
||||
let mut layout_ctx = layout_ctx.borrow_mut();
|
||||
self.handle_shortcut(&mut layout_ctx, key, &mods, atom).await
|
||||
})
|
||||
return self.handle_shortcut(key, &mods, atom).await
|
||||
}
|
||||
|
||||
// Do nothing
|
||||
@@ -1640,10 +1631,7 @@ impl UIObject for BaseEdit {
|
||||
|
||||
let mut is_handled = false;
|
||||
for _ in 0..actions {
|
||||
is_handled = text::THREAD_LAYOUT_CTX.with(|layout_ctx| {
|
||||
let mut layout_ctx = layout_ctx.borrow_mut();
|
||||
self.handle_key(&mut layout_ctx, &key, &mods, atom).await
|
||||
});
|
||||
is_handled = self.handle_key(&key, &mods, atom).await;
|
||||
}
|
||||
is_handled
|
||||
}
|
||||
@@ -1684,12 +1672,10 @@ impl UIObject for BaseEdit {
|
||||
// Move mouse pos within this widget
|
||||
self.abs_to_local(&mut mouse_pos);
|
||||
|
||||
text::THREAD_LAYOUT_CTX.with(|layout_ctx| {
|
||||
let mut layout_ctx = layout_ctx.borrow_mut();
|
||||
{
|
||||
let mut editor = self.lock_editor().await;
|
||||
let mut drv = editor.driver(&mut layout_ctx);
|
||||
drv.move_to_point(mouse_pos.x, mouse_pos.y);
|
||||
});
|
||||
editor.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();
|
||||
|
||||
@@ -123,7 +123,8 @@ impl Text {
|
||||
text
|
||||
};
|
||||
|
||||
let layout = text::make_layout(&text, text_color, font_size, lineheight, window_scale, None, &[]);
|
||||
let layout =
|
||||
text::make_layout(&text, text_color, font_size, lineheight, window_scale, None, &[]);
|
||||
|
||||
let mut debug_opts = text::DebugRenderOptions::OFF;
|
||||
if self.debug.get() {
|
||||
|
||||
Reference in New Issue
Block a user