ltk/event_loop/text_editing/
cursor.rsuse crate::app::App;
use crate::event_loop::app_data::AppData;
use crate::event_loop::surface::SurfaceFocus;
impl<A: App> AppData<A>
{
pub( crate ) fn focused_text_value( &self, focus: SurfaceFocus ) -> Option<( usize, String )>
{
let idx = self.surface( focus ).focused_idx?;
let value = if let Some( pending ) = self.surface( focus ).pending_text_values.get( &idx )
{
pending.clone()
} else {
crate::tree::find_handlers( &self.surface( focus ).widget_rects, idx )?
.current_value()
.map( |s| s.to_string() )
.unwrap_or_default()
};
Some( ( idx, value ) )
}
pub( crate ) fn handle_cursor_left( &mut self, focus: SurfaceFocus, extend: bool )
{
let ( idx, value ) = match self.focused_text_value( focus ) { Some( v ) => v, None => return };
let cursor = self.surface( focus ).cursor_state.get( &idx ).copied()
.unwrap_or( value.len() ).min( value.len() );
let anchor = self.surface( focus ).selection_anchor.get( &idx ).copied()
.unwrap_or( cursor ).min( value.len() );
if !extend && anchor != cursor
{
let s = cursor.min( anchor );
let ss = self.surface_mut( focus );
*ss.cursor_state.entry( idx ).or_insert( 0 ) = s;
*ss.selection_anchor.entry( idx ).or_insert( 0 ) = s;
ss.request_redraw();
return;
}
if cursor == 0 { return; }
let prev_char = value[..cursor].chars().last();
let step = prev_char.map( |c| c.len_utf8() ).unwrap_or( 1 );
let new_cursor = cursor.saturating_sub( step );
let ss = self.surface_mut( focus );
*ss.cursor_state.entry( idx ).or_insert( 0 ) = new_cursor;
if !extend { *ss.selection_anchor.entry( idx ).or_insert( 0 ) = new_cursor; }
ss.request_redraw();
}
pub( crate ) fn handle_cursor_right( &mut self, focus: SurfaceFocus, extend: bool )
{
let ( idx, value ) = match self.focused_text_value( focus ) { Some( v ) => v, None => return };
let cursor = self.surface( focus ).cursor_state.get( &idx ).copied()
.unwrap_or( value.len() ).min( value.len() );
let anchor = self.surface( focus ).selection_anchor.get( &idx ).copied()
.unwrap_or( cursor ).min( value.len() );
if !extend && anchor != cursor
{
let e = cursor.max( anchor );
let ss = self.surface_mut( focus );
*ss.cursor_state.entry( idx ).or_insert( 0 ) = e;
*ss.selection_anchor.entry( idx ).or_insert( 0 ) = e;
ss.request_redraw();
return;
}
if cursor >= value.len() { return; }
let next_char = value[cursor..].chars().next();
let step = next_char.map( |c| c.len_utf8() ).unwrap_or( 1 );
let new_cursor = ( cursor + step ).min( value.len() );
let ss = self.surface_mut( focus );
*ss.cursor_state.entry( idx ).or_insert( 0 ) = new_cursor;
if !extend { *ss.selection_anchor.entry( idx ).or_insert( 0 ) = new_cursor; }
ss.request_redraw();
}
pub( crate ) fn handle_cursor_up( &mut self, focus: SurfaceFocus, extend: bool ) -> bool
{
let ( idx, value ) = match self.focused_text_value( focus ) { Some( v ) => v, None => return false };
let cursor = self.surface( focus ).cursor_state.get( &idx ).copied()
.unwrap_or( value.len() ).min( value.len() );
let ( rect, _, multiline, secure, _align, _font_size ) = match self.text_input_geometry( focus, idx )
{
Some( g ) => g,
None => return false,
};
if !multiline || secure { return false; }
let canvas = match self.surface( focus ).canvas.as_ref() { Some( c ) => c, None => return false };
let new_cursor = match crate::widget::text_edit::cursor_visual_up( canvas, rect, &value, cursor )
{
Some( n ) => n,
None => return false,
};
let ss = self.surface_mut( focus );
*ss.cursor_state.entry( idx ).or_insert( 0 ) = new_cursor;
if !extend { *ss.selection_anchor.entry( idx ).or_insert( 0 ) = new_cursor; }
ss.request_redraw();
true
}
pub( crate ) fn handle_cursor_down( &mut self, focus: SurfaceFocus, extend: bool ) -> bool
{
let ( idx, value ) = match self.focused_text_value( focus ) { Some( v ) => v, None => return false };
let cursor = self.surface( focus ).cursor_state.get( &idx ).copied()
.unwrap_or( value.len() ).min( value.len() );
let ( rect, _, multiline, secure, _align, _font_size ) = match self.text_input_geometry( focus, idx )
{
Some( g ) => g,
None => return false,
};
if !multiline || secure { return false; }
let canvas = match self.surface( focus ).canvas.as_ref() { Some( c ) => c, None => return false };
let new_cursor = match crate::widget::text_edit::cursor_visual_down( canvas, rect, &value, cursor )
{
Some( n ) => n,
None => return false,
};
let ss = self.surface_mut( focus );
*ss.cursor_state.entry( idx ).or_insert( 0 ) = new_cursor;
if !extend { *ss.selection_anchor.entry( idx ).or_insert( 0 ) = new_cursor; }
ss.request_redraw();
true
}
pub( crate ) fn handle_cursor_home( &mut self, focus: SurfaceFocus, extend: bool )
{
let ( idx, value ) = match self.focused_text_value( focus ) { Some( v ) => v, None => return };
let cursor = self.surface( focus ).cursor_state.get( &idx ).copied()
.unwrap_or( value.len() ).min( value.len() );
let new_cursor = match self.text_input_geometry( focus, idx )
{
Some( ( rect, _, true, false, _, _ ) ) => match self.surface( focus ).canvas.as_ref()
{
Some( canvas ) => crate::widget::text_edit::cursor_visual_home( canvas, rect, &value, cursor ),
None => value[..cursor].rfind( '\n' ).map( |p| p + 1 ).unwrap_or( 0 ),
},
_ => value[..cursor].rfind( '\n' ).map( |p| p + 1 ).unwrap_or( 0 ),
};
let ss = self.surface_mut( focus );
*ss.cursor_state.entry( idx ).or_insert( 0 ) = new_cursor;
if !extend { *ss.selection_anchor.entry( idx ).or_insert( 0 ) = new_cursor; }
ss.request_redraw();
}
pub( crate ) fn handle_cursor_end( &mut self, focus: SurfaceFocus, extend: bool )
{
let ( idx, value ) = match self.focused_text_value( focus ) { Some( v ) => v, None => return };
let cursor = self.surface( focus ).cursor_state.get( &idx ).copied()
.unwrap_or( value.len() ).min( value.len() );
let new_cursor = match self.text_input_geometry( focus, idx )
{
Some( ( rect, _, true, false, _, _ ) ) => match self.surface( focus ).canvas.as_ref()
{
Some( canvas ) => crate::widget::text_edit::cursor_visual_end( canvas, rect, &value, cursor ),
None => value[cursor..].find( '\n' ).map( |p| cursor + p ).unwrap_or( value.len() ),
},
_ => value[cursor..].find( '\n' ).map( |p| cursor + p ).unwrap_or( value.len() ),
};
let ss = self.surface_mut( focus );
*ss.cursor_state.entry( idx ).or_insert( 0 ) = new_cursor;
if !extend { *ss.selection_anchor.entry( idx ).or_insert( 0 ) = new_cursor; }
ss.request_redraw();
}
}