use cranpose_foundation::text::{TextFieldLineLimits, TextFieldState};
use std::rc::Rc;
use crate::text_field_input::handle_key_event_impl;
pub(crate) struct TextFieldHandler {
state: TextFieldState,
node_id: Option<cranpose_core::NodeId>,
line_limits: TextFieldLineLimits,
}
impl TextFieldHandler {
pub(crate) fn new(
state: TextFieldState,
node_id: Option<cranpose_core::NodeId>,
line_limits: TextFieldLineLimits,
) -> Rc<Self> {
Rc::new(Self {
state,
node_id,
line_limits,
})
}
}
impl crate::text_field_focus::FocusedTextFieldHandler for TextFieldHandler {
fn handle_key(&self, event: &crate::key_event::KeyEvent) -> bool {
use crate::key_event::KeyEventType;
if event.event_type != KeyEventType::KeyDown {
return false;
}
let consumed = handle_key_event_impl(&self.state, event, self.line_limits);
if consumed {
crate::cursor_animation::reset_cursor_blink();
if let Some(node_id) = self.node_id {
crate::schedule_layout_repass(node_id);
}
crate::request_render_invalidation();
}
consumed
}
fn insert_text(&self, text: &str) {
self.state.edit(|buffer| {
buffer.insert(text);
});
crate::cursor_animation::reset_cursor_blink();
if let Some(node_id) = self.node_id {
crate::schedule_layout_repass(node_id);
}
crate::request_render_invalidation();
}
fn delete_surrounding(&self, before_bytes: usize, after_bytes: usize) {
if before_bytes == 0 && after_bytes == 0 {
return;
}
self.state.edit(|buffer| {
buffer.delete_surrounding(before_bytes, after_bytes);
});
self.state.set_desired_column(None);
crate::cursor_animation::reset_cursor_blink();
if let Some(node_id) = self.node_id {
crate::schedule_layout_repass(node_id);
}
crate::request_render_invalidation();
}
fn copy_selection(&self) -> Option<String> {
let value = self.state.value();
let selection = value.selection;
if selection.collapsed() {
return None;
}
let text = selection.safe_slice(&value.text);
if text.is_empty() {
return None;
}
Some(text.to_string())
}
fn cut_selection(&self) -> Option<String> {
let value = self.state.value();
let selection = value.selection;
if selection.collapsed() {
return None;
}
let text = selection.safe_slice(&value.text);
if text.is_empty() {
return None;
}
let text = text.to_string();
self.state.edit(|buffer| {
buffer.delete(selection);
});
crate::cursor_animation::reset_cursor_blink();
crate::request_render_invalidation();
Some(text)
}
fn set_composition(&self, text: &str, cursor: Option<(usize, usize)>) {
self.state.edit(|buffer| {
if text.is_empty() {
if let Some(range) = buffer.composition() {
buffer.delete(range);
}
buffer.set_composition(None);
} else {
let insert_pos = buffer.selection().min();
let comp_end = insert_pos + text.len();
buffer.replace(buffer.selection(), text);
let comp_range = cranpose_foundation::text::TextRange::new(insert_pos, comp_end);
buffer.set_composition(Some(comp_range));
if let Some((cursor_start, _cursor_end)) = cursor {
let cursor_pos = insert_pos + cursor_start.min(text.len());
buffer.place_cursor_before_char(cursor_pos);
}
}
});
crate::request_render_invalidation();
}
}