ltk/event_loop/text_editing/
insert_delete.rsuse crate::app::App;
use crate::event_loop::app_data::AppData;
use crate::event_loop::surface::SurfaceFocus;
use crate::tree::find_handlers;
use crate::widget::WidgetHandlers;
impl<A: App> AppData<A>
{
pub( crate ) fn handle_text_insert( &mut self, focus: SurfaceFocus, text: &str )
{
let idx = match self.surface( focus ).focused_idx { Some( i ) => i, None => return };
let _ = self.delete_selection( focus );
let current_value = if let Some( pending ) = self.surface( focus ).pending_text_values.get( &idx )
{
pending.clone()
} else {
find_handlers( &self.surface( focus ).widget_rects, idx )
.and_then( |h| h.current_value() )
.map( |s| s.to_string() )
.unwrap_or_default()
};
let select_on_focus = matches!(
find_handlers( &self.surface( focus ).widget_rects, idx ),
Some( WidgetHandlers::TextEdit { select_on_focus: true, .. } ),
);
let new_value;
{
let ss = self.surface_mut( focus );
let cursor = ss.cursor_state.entry( idx ).or_insert( current_value.len() );
let safe_cursor = (*cursor).min( current_value.len() );
let mut v = current_value.clone();
v.insert_str( safe_cursor, text );
let next_cursor = if select_on_focus { usize::MAX } else { safe_cursor + text.len() };
*ss.cursor_state.entry( idx ).or_insert( 0 ) = next_cursor;
*ss.selection_anchor.entry( idx ).or_insert( 0 ) = next_cursor;
ss.pending_text_values.insert( idx, v.clone() );
ss.request_redraw();
new_value = v;
}
let msg = find_handlers( &self.surface( focus ).widget_rects, idx )
.and_then( |h| h.text_change_msg( &new_value ) );
if let Some( m ) = msg
{
self.pending_msgs.push( m );
}
}
pub( crate ) fn handle_delete_forward( &mut self, focus: SurfaceFocus )
{
let idx = match self.surface( focus ).focused_idx { Some( i ) => i, None => return };
if let Some( new_value ) = self.delete_selection( focus )
{
let msg = find_handlers( &self.surface( focus ).widget_rects, idx )
.and_then( |h| h.text_change_msg( &new_value ) );
if let Some( m ) = msg { self.pending_msgs.push( m ); }
return;
}
let current_value = if let Some( pending ) = self.surface( focus ).pending_text_values.get( &idx )
{
pending.clone()
} else {
find_handlers( &self.surface( focus ).widget_rects, idx )
.and_then( |h| h.current_value() )
.map( |s| s.to_string() )
.unwrap_or_default()
};
let cursor_val = self.surface( focus ).cursor_state.get( &idx ).copied()
.unwrap_or( current_value.len() );
let safe_cursor_pre = cursor_val.min( current_value.len() );
if safe_cursor_pre >= current_value.len() { return; }
let next_char = current_value[safe_cursor_pre..].chars().next();
let step = match next_char { Some( c ) => c.len_utf8(), None => return };
let mut new_value = current_value.clone();
new_value.replace_range( safe_cursor_pre..safe_cursor_pre + step, "" );
let select_on_focus = matches!(
find_handlers( &self.surface( focus ).widget_rects, idx ),
Some( WidgetHandlers::TextEdit { select_on_focus: true, .. } ),
);
let next_cursor = if select_on_focus { usize::MAX } else { safe_cursor_pre };
{
let ss = self.surface_mut( focus );
*ss.cursor_state.entry( idx ).or_insert( 0 ) = next_cursor;
*ss.selection_anchor.entry( idx ).or_insert( 0 ) = next_cursor;
ss.pending_text_values.insert( idx, new_value.clone() );
ss.request_redraw();
}
let msg = find_handlers( &self.surface( focus ).widget_rects, idx )
.and_then( |h| h.text_change_msg( &new_value ) );
if let Some( m ) = msg
{
self.pending_msgs.push( m );
}
}
pub( crate ) fn handle_delete_surrounding( &mut self, focus: SurfaceFocus, before_bytes: u32, after_bytes: u32 )
{
let idx = match self.surface( focus ).focused_idx { Some( i ) => i, None => return };
let _ = self.delete_selection( focus );
let current_value = if let Some( pending ) = self.surface( focus ).pending_text_values.get( &idx )
{
pending.clone()
} else {
find_handlers( &self.surface( focus ).widget_rects, idx )
.and_then( |h| h.current_value() )
.map( |s| s.to_string() )
.unwrap_or_default()
};
let cursor_val = self.surface( focus ).cursor_state.get( &idx ).copied()
.unwrap_or( current_value.len() );
let safe_cursor = cursor_val.min( current_value.len() );
let start_byte =
{
let mut pos = safe_cursor;
for ( i, _ ) in current_value[..safe_cursor].char_indices().rev()
{
if ( safe_cursor - pos ) as u32 >= before_bytes { break; }
pos = i;
}
pos
};
let end_byte =
{
let mut pos = safe_cursor;
for ( i, ch ) in current_value[safe_cursor..].char_indices()
{
if ( pos - safe_cursor ) as u32 >= after_bytes { break; }
pos = safe_cursor + i + ch.len_utf8();
}
pos
};
if start_byte >= end_byte { return; }
let mut new_value = current_value.clone();
new_value.replace_range( start_byte..end_byte, "" );
let select_on_focus = matches!(
find_handlers( &self.surface( focus ).widget_rects, idx ),
Some( WidgetHandlers::TextEdit { select_on_focus: true, .. } ),
);
let next_cursor = if select_on_focus { usize::MAX } else { start_byte };
{
let ss = self.surface_mut( focus );
*ss.cursor_state.entry( idx ).or_insert( 0 ) = next_cursor;
*ss.selection_anchor.entry( idx ).or_insert( 0 ) = next_cursor;
ss.pending_text_values.insert( idx, new_value.clone() );
ss.request_redraw();
}
let msg = find_handlers( &self.surface( focus ).widget_rects, idx )
.and_then( |h| h.text_change_msg( &new_value ) );
if let Some( m ) = msg
{
self.pending_msgs.push( m );
}
}
pub( crate ) fn handle_backspace( &mut self, focus: SurfaceFocus )
{
let idx = match self.surface( focus ).focused_idx { Some( i ) => i, None => return };
if let Some( new_value ) = self.delete_selection( focus )
{
let msg = find_handlers( &self.surface( focus ).widget_rects, idx )
.and_then( |h| h.text_change_msg( &new_value ) );
if let Some( m ) = msg { self.pending_msgs.push( m ); }
return;
}
let current_value = if let Some( pending ) = self.surface( focus ).pending_text_values.get( &idx )
{
pending.clone()
} else {
find_handlers( &self.surface( focus ).widget_rects, idx )
.and_then( |h| h.current_value() )
.map( |s| s.to_string() )
.unwrap_or_default()
};
let cursor_val = self.surface( focus ).cursor_state.get( &idx ).copied()
.unwrap_or( current_value.len() );
if cursor_val == 0 { return; }
let safe_cursor = cursor_val.min( current_value.len() );
let chars: Vec<char> = current_value[..safe_cursor].chars().collect();
if chars.is_empty() { return; }
let removed_char = *chars.last().unwrap();
let new_cursor = safe_cursor - removed_char.len_utf8();
let mut new_value = current_value.clone();
new_value.remove( new_cursor );
let select_on_focus = matches!(
find_handlers( &self.surface( focus ).widget_rects, idx ),
Some( WidgetHandlers::TextEdit { select_on_focus: true, .. } ),
);
let next_cursor = if select_on_focus { usize::MAX } else { new_cursor };
{
let ss = self.surface_mut( focus );
*ss.cursor_state.entry( idx ).or_insert( 0 ) = next_cursor;
*ss.selection_anchor.entry( idx ).or_insert( 0 ) = next_cursor;
ss.pending_text_values.insert( idx, new_value.clone() );
ss.request_redraw();
}
let msg = find_handlers( &self.surface( focus ).widget_rects, idx )
.and_then( |h| h.text_change_msg( &new_value ) );
if let Some( m ) = msg
{
self.pending_msgs.push( m );
}
}
}