teksilo_widgets/common/
standard_edit.rs1use std::rc::Rc;
14
15use teksilo_core::action::Action;
16use teksilo_core::build_context::BuildContext;
17use teksilo_core::intent::IntentResponse;
18use teksilo_core::shortcut::{ShortcutRegistry, StandardEdit};
19use teksilo_core::widget::EventContext;
20use teksilo_i18n::{LocalizedString, tr_widget};
21
22pub(crate) fn register_standard_edit_actions(
29 ctx: &mut BuildContext,
30 run: impl Fn(StandardEdit, &mut EventContext) -> bool + 'static,
31) {
32 let run = Rc::new(run);
33 for command in StandardEdit::ALL {
34 let run = Rc::clone(&run);
35 register_standard_edit_action(ctx, command, move |ctx| run(command, ctx));
36 }
37}
38
39pub(crate) fn register_standard_edit_action(
42 ctx: &mut BuildContext,
43 command: StandardEdit,
44 run: impl FnMut(&mut EventContext) -> bool + 'static,
45) {
46 register_command_action(ctx, command.id(), run);
47}
48
49pub(crate) fn register_command_action(
55 ctx: &mut BuildContext,
56 id: &'static str,
57 mut run: impl FnMut(&mut EventContext) -> bool + 'static,
58) {
59 ctx.register_action(
60 Action::new(id).on_invoke_with_response(move |_intent, ctx| {
61 if run(ctx) {
62 IntentResponse::Handled
63 } else {
64 IntentResponse::Propagated
65 }
66 }),
67 );
68}
69
70pub fn localize_standard_shortcuts(registry: &mut ShortcutRegistry) {
78 if teksilo_i18n::thread_local::with_active(|_| ()).is_none() {
79 return;
80 }
81 for command in StandardEdit::ALL {
82 let Some(name) = localized_name(command) else {
83 continue;
84 };
85 let mut shortcut = command.shortcut();
86 shortcut.name = name.into();
87 shortcut.category_label = Some(tr_widget!(shortcut_category_edit()).into());
88 registry.register(shortcut);
89 }
90}
91
92fn localized_name(command: StandardEdit) -> Option<LocalizedString> {
95 Some(match command {
96 StandardEdit::Cut => tr_widget!(menu_cut()),
97 StandardEdit::Copy => tr_widget!(menu_copy()),
98 StandardEdit::Paste => tr_widget!(menu_paste()),
99 StandardEdit::PastePlain => tr_widget!(menu_paste_unformatted()),
100 StandardEdit::Undo => tr_widget!(menu_undo()),
101 StandardEdit::Redo => tr_widget!(menu_redo()),
102 StandardEdit::SelectAll => tr_widget!(menu_select_all()),
103 _ => return None,
104 })
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110 use crate::common::locale_switch_test::speaking;
111
112 fn shown(registry: &ShortcutRegistry, command: StandardEdit) -> (String, Option<String>) {
113 let effective = registry.effective(command.id()).expect("registered");
114 (
115 effective.shortcut.name.get(),
116 effective.shortcut.category_text(),
117 )
118 }
119
120 #[test]
121 fn the_names_follow_the_language_and_the_bindings_survive() {
122 let (mgr, mut tree) = speaking("fr-FR");
123 let undo_too = teksilo_core::shortcut::KeyStroke::new(
124 teksilo_core::event::Key::Character('à'),
125 teksilo_core::event::Modifiers::CTRL,
126 );
127 tree.shortcut_registry_mut()
128 .rebind_secondary(StandardEdit::Undo.id(), Some(undo_too));
129
130 localize_standard_shortcuts(tree.shortcut_registry_mut());
131 let registry = tree.shortcut_registry();
132 assert_eq!(
133 shown(registry, StandardEdit::Undo),
134 ("Annuler".to_string(), Some("Édition".to_string()))
135 );
136 assert_eq!(
137 shown(registry, StandardEdit::SelectAll).0,
138 "Tout sélectionner"
139 );
140 assert_eq!(
141 registry
142 .effective(StandardEdit::Undo.id())
143 .unwrap()
144 .secondary,
145 Some(undo_too),
146 "localizing must not drop a user's binding"
147 );
148
149 mgr.set_locale("en-US".parse().unwrap());
150 assert_eq!(
151 shown(tree.shortcut_registry(), StandardEdit::Undo),
152 ("Undo".to_string(), Some("Edit".to_string())),
153 "the names follow a change of language"
154 );
155 teksilo_i18n::thread_local::clear();
156 }
157
158 #[test]
159 fn without_a_manager_the_english_names_stay() {
160 teksilo_i18n::thread_local::clear();
161 let mut tree = teksilo_core::widget_tree::WidgetTree::new();
162 localize_standard_shortcuts(tree.shortcut_registry_mut());
163 assert_eq!(
164 shown(tree.shortcut_registry(), StandardEdit::PastePlain),
165 ("Paste Unformatted".to_string(), Some("Edit".to_string()))
166 );
167 }
168}