diff --git a/crates/ui-egui/src/panels/right.rs b/crates/ui-egui/src/panels/right.rs index f4c5fe899..f6e6d3f96 100644 --- a/crates/ui-egui/src/panels/right.rs +++ b/crates/ui-egui/src/panels/right.rs @@ -802,16 +802,22 @@ fn keywords(app: &mut LightcraftApp, ui: &mut egui::Ui, id: PhotoId) { let pid = egui::Id::new("kw-painter"); let painting = app.ui.keyword_painter.clone(); let mut k: String = ui.data(|d| d.get_temp(pid)).unwrap_or_else(|| painting.clone().unwrap_or_default()); - let r = ui.add_enabled( - painting.is_none(), - egui::TextEdit::singleline(&mut k).hint_text(crate::i18n::tr("Keyword to paint")).desired_width(130.0), - ); - register(ui.ctx(), "field:keywordPainter", r.rect); + // (fixed while painting: Stop first) + let field = ui + .add_enabled_ui(painting.is_none(), |ui| { + crate::text_field::TextField::singleline("field:keywordPainter", &mut k) + .hint(crate::i18n::tr("Keyword to paint")) + .width(130.0) + .show(ui) + }) + .inner; ui.data_mut(|d| d.insert_temp(pid, k.clone())); let label = if painting.is_some() { "Stop" } else { "Paint" }; + let returned = field.ending == Some(crate::text_field::Ending::Return) && painting.is_none() && !k.trim().is_empty(); if text_button(ui, "keywordPaint", label, painting.is_some()) .on_hover_text(crate::i18n::tr("Click photos in the grid to toggle the keyword; Esc stops")) .clicked() + || returned { let _ = app.run("tool.keywordPainter", json!({"keyword": if painting.is_some() { serde_json::Value::Null } else { json!(k) }})); } diff --git a/crates/ui-egui/src/tests_keywording.rs b/crates/ui-egui/src/tests_keywording.rs index 3de8c53a0..167ddb4d5 100644 --- a/crates/ui-egui/src/tests_keywording.rs +++ b/crates/ui-egui/src/tests_keywording.rs @@ -134,3 +134,15 @@ fn will_export_shows_what_exports_carry() { ask(&mut h, "ui.clickWidget", json!({"id": "keywordView:keywords"})); assert!(has(&h, "keywordChip:beach") && !has(&h, "keywordExport:beach")); } + +/// The painter's keyword field is a shared text field: right-click ▸ Paste fills it, and Return +/// starts painting as the Paint button does. +#[test] +fn the_painters_field_pastes_and_return_paints() { + let (mut h, _) = two_selected(); + h.view.clipboard = "Weddings".into(); + ask(&mut h, "ui.clickWidget", json!({"id": "field:keywordPainter", "button": "right"})); + ask(&mut h, "ui.clickWidget", json!({"id": "field:keywordPainter:paste"})); + ask(&mut h, "ui.key", json!({"key": "Enter"})); + assert_eq!(h.app.ui.keyword_painter.as_deref(), Some("Weddings")); +}