I'm trying to get the selection of a TextInput. I see that there is a public text_input::State::cursor() returning a Cursor, which has a public state() method. However, I can't call Cursor::state() because it takes a text_input::value::Value, which doesn't seem to be exposed, and even if I could call it, I don't think text_input::cursor::State is exposed in order to match on the return value. I can understand why cursor::State and Value would be kept private if users are supposed to go through text_input::State as a wrapper around them, but then I'm not sure why text_input::State::cursor() would ever be used as a public method, since everything else on Cursor is private. Am I missing something?
iced_graphics uses the Cursor API to draw a TextInput:
Ah, so it supports cases where you're working directly with the iced_native crate rather than just the iced crate. Thanks for the quick response! (This made me realize that I can just add iced_native as an additional dependency to accomplish what I'm trying to do.)
Would you be open to adding methods to text_input::State for accessing the cursor selection (similar to how move_cursor_to_end works)?
Would you be open to adding methods to text_input::State for accessing the cursor selection (similar to how move_cursor_to_end works)?
Maybe! What are the use cases you have in mind?
Might be unrelated, but when working with input field tabbing I noticed a select_all method would be useful.
My particular use case is that I'm using a Subscription to implement my own copy/cut/undo/redo shortcuts (I'd like to figure out how to contribute them back if possible, but for now I just need to get something working). For copy/cut, I need to know what's currently selected, and for cut, I also need to delete the selected part of the text and clear the selection:
// in update()
match shortcut {
// backup_target_input is a text_input::State, and backup_target_history is my own TextHistory
Shortcut::ClipboardCut => {
self.config.backup.path = crate::shortcuts::cut_to_clipboard_from_iced(&self.config.backup.path, &self.backup_screen.backup_target_input.cursor());
self.backup_screen.backup_target_history.push(&self.config.backup.path);
},
}
pub fn cut_to_clipboard_from_iced(text: &str, cursor: &iced_native::text_input::Cursor) -> String {
let value = iced_native::text_input::Value::new(text);
match cursor.state(&value) {
iced_native::text_input::cursor::State::Selection { start, end } => {
match cut_to_clipboard(&text, std::cmp::min(start, end), std::cmp::max(start, end)) {
Ok(remaining) => {
// TODO: Clear the selection?
remaining.to_owned(),
}
Err(_) => text.to_owned(),
}
}
_ => text.to_owned(),
}
}
Incidentally, cutting and then immediately pasting causes a panic in iced_native::widget::text_input::value::Value::remove_many, called by iced_native::widget::text_input::editor::Editor::paste. The TextInput doesn't seem to realize that the text has changed, so it's still working based on the previous length. I'm still trying to figure out how to make a fix for that. Here's a simple gist, and here's the main part of the backtrace based on latest master code:
thread 'main' panicked at 'end drain index (is 28) should be <= len (is 8)', src\liballoc\vec.rs:1331:13
[...]
15: iced_native::widget::text_input::value::Value::remove_many
at C:\Users\mtken\.cargo\git\checkouts\iced-2bccc042db34f88f\3172bd3\native\src\widget\text_input\value.rs:120
16: iced_native::widget::text_input::editor::Editor::paste
at C:\Users\mtken\.cargo\git\checkouts\iced-2bccc042db34f88f\3172bd3\native\src\widget\text_input\editor.rs:36
17: iced_native::widget::text_input::{{impl}}::on_event<paste_panic::Message,iced_graphics::renderer::Renderer<iced_wgpu::backend::Backend>>
at C:\Users\mtken\.cargo\git\checkouts\iced-2bccc042db34f88f\3172bd3\native\src\widget\text_input.rs:448
[...]
Most helpful comment
Might be unrelated, but when working with input field tabbing I noticed a
select_allmethod would be useful.