core: Add EditText::is_text_control_applicable

This method is useful for checking whether the given text control code
may be applied to the current state of the EditText.
This commit is contained in:
Kamil Jarosz 2024-06-06 23:46:16 +02:00 committed by Nathan Adams
parent 1f3c230691
commit 0910104c3b
2 changed files with 235 additions and 155 deletions

View File

@ -127,6 +127,70 @@ impl<'gc> ContextMenuState<'gc> {
); );
} }
} }
fn build_text_items(&mut self, text: EditText<'gc>, context: &mut UpdateContext<'_, 'gc>) {
let language = &context.ui.language();
self.push(
ContextMenuItem {
enabled: text.is_text_control_applicable(TextControlCode::Cut),
separator_before: true,
caption: core_text(language, "context-menu-cut"),
checked: false,
},
ContextMenuCallback::TextControl {
code: TextControlCode::Cut,
text,
},
);
self.push(
ContextMenuItem {
enabled: text.is_text_control_applicable(TextControlCode::Copy),
separator_before: false,
caption: core_text(language, "context-menu-copy"),
checked: false,
},
ContextMenuCallback::TextControl {
code: TextControlCode::Copy,
text,
},
);
self.push(
ContextMenuItem {
enabled: text.is_text_control_applicable(TextControlCode::Paste),
separator_before: false,
caption: core_text(language, "context-menu-paste"),
checked: false,
},
ContextMenuCallback::TextControl {
code: TextControlCode::Paste,
text,
},
);
self.push(
ContextMenuItem {
enabled: text.is_text_control_applicable(TextControlCode::Delete),
separator_before: false,
caption: core_text(language, "context-menu-delete"),
checked: false,
},
ContextMenuCallback::TextControl {
code: TextControlCode::Delete,
text,
},
);
self.push(
ContextMenuItem {
enabled: text.is_text_control_applicable(TextControlCode::SelectAll),
separator_before: true,
caption: core_text(language, "context-menu-select-all"),
checked: false,
},
ContextMenuCallback::TextControl {
code: TextControlCode::SelectAll,
text,
},
);
}
} }
#[derive(Clone, Serialize)] #[derive(Clone, Serialize)]

View File

@ -1420,16 +1420,43 @@ impl<'gc> EditText<'gc> {
} }
} }
pub fn is_text_control_applicable(self, control_code: TextControlCode) -> bool {
if !self.is_editable() && control_code.is_edit_input() {
return false;
}
let Some(selection) = self.selection() else {
return false;
};
match control_code {
TextControlCode::SelectLeft
| TextControlCode::SelectLeftWord
| TextControlCode::SelectLeftLine
| TextControlCode::SelectLeftDocument
| TextControlCode::SelectRight
| TextControlCode::SelectRightWord
| TextControlCode::SelectRightLine
| TextControlCode::SelectRightDocument
| TextControlCode::SelectAll => self.is_selectable(),
TextControlCode::Copy | TextControlCode::Cut => !selection.is_caret(),
_ => true,
}
}
pub fn text_control_input( pub fn text_control_input(
self, self,
control_code: TextControlCode, control_code: TextControlCode,
context: &mut UpdateContext<'_, 'gc>, context: &mut UpdateContext<'_, 'gc>,
) { ) {
if !self.is_editable() && control_code.is_edit_input() { if !self.is_text_control_applicable(control_code) {
return; return;
} }
if let Some(selection) = self.selection() { let Some(selection) = self.selection() else {
return;
};
let mut changed = false; let mut changed = false;
let is_selectable = self.is_selectable(); let is_selectable = self.is_selectable();
match control_code { match control_code {
@ -1468,7 +1495,7 @@ impl<'gc> EditText<'gc> {
| TextControlCode::SelectLeftWord | TextControlCode::SelectLeftWord
| TextControlCode::SelectLeftLine | TextControlCode::SelectLeftLine
| TextControlCode::SelectLeftDocument => { | TextControlCode::SelectLeftDocument => {
if is_selectable && selection.to > 0 { if selection.to > 0 {
let new_pos = self.find_new_position(control_code, selection.to); let new_pos = self.find_new_position(control_code, selection.to);
self.set_selection( self.set_selection(
Some(TextSelection::for_range(selection.from, new_pos)), Some(TextSelection::for_range(selection.from, new_pos)),
@ -1480,7 +1507,7 @@ impl<'gc> EditText<'gc> {
| TextControlCode::SelectRightWord | TextControlCode::SelectRightWord
| TextControlCode::SelectRightLine | TextControlCode::SelectRightLine
| TextControlCode::SelectRightDocument => { | TextControlCode::SelectRightDocument => {
if is_selectable && selection.to < self.text().len() { if selection.to < self.text().len() {
let new_pos = self.find_new_position(control_code, selection.to); let new_pos = self.find_new_position(control_code, selection.to);
self.set_selection( self.set_selection(
Some(TextSelection::for_range(selection.from, new_pos)), Some(TextSelection::for_range(selection.from, new_pos)),
@ -1489,21 +1516,18 @@ impl<'gc> EditText<'gc> {
} }
} }
TextControlCode::SelectAll => { TextControlCode::SelectAll => {
if is_selectable {
self.set_selection( self.set_selection(
Some(TextSelection::for_range(0, self.text().len())), Some(TextSelection::for_range(0, self.text().len())),
context.gc_context, context.gc_context,
); );
} }
}
TextControlCode::Copy => { TextControlCode::Copy => {
if !selection.is_caret() {
let text = &self.text()[selection.start()..selection.end()]; let text = &self.text()[selection.start()..selection.end()];
context.ui.set_clipboard_content(text.to_string()); context.ui.set_clipboard_content(text.to_string());
} }
}
TextControlCode::Paste => { TextControlCode::Paste => {
let text = context.ui.clipboard_content(); let text = context.ui.clipboard_content();
let mut text = self.0.read().restrict.filter_allowed(&text); let mut text = self.0.read().restrict.filter_allowed(&text);
if text.len() > self.available_chars() && self.available_chars() > 0 { if text.len() > self.available_chars() && self.available_chars() > 0 {
@ -1533,16 +1557,10 @@ impl<'gc> EditText<'gc> {
} }
} }
TextControlCode::Cut => { TextControlCode::Cut => {
if !selection.is_caret() {
let text = &self.text()[selection.start()..selection.end()]; let text = &self.text()[selection.start()..selection.end()];
context.ui.set_clipboard_content(text.to_string()); context.ui.set_clipboard_content(text.to_string());
self.replace_text( self.replace_text(selection.start(), selection.end(), WStr::empty(), context);
selection.start(),
selection.end(),
WStr::empty(),
context,
);
if is_selectable { if is_selectable {
self.set_selection( self.set_selection(
Some(TextSelection::for_position(selection.start())), Some(TextSelection::for_position(selection.start())),
@ -1556,7 +1574,6 @@ impl<'gc> EditText<'gc> {
} }
changed = true; changed = true;
} }
}
TextControlCode::Backspace TextControlCode::Backspace
| TextControlCode::BackspaceWord | TextControlCode::BackspaceWord
| TextControlCode::Delete | TextControlCode::Delete
@ -1606,7 +1623,6 @@ impl<'gc> EditText<'gc> {
self.on_changed(&mut activation); self.on_changed(&mut activation);
} }
} }
}
/// Find the new position in the text for the given control code. /// Find the new position in the text for the given control code.
/// ///