diff --git a/crates/ui-egui/src/canvas/pick.rs b/crates/ui-egui/src/canvas/pick.rs index 112740d06..3bd28b017 100644 --- a/crates/ui-egui/src/canvas/pick.rs +++ b/crates/ui-egui/src/canvas/pick.rs @@ -1,4 +1,4 @@ -use super::{CadApp, Handle, Vec2}; +use super::{CadApp, Handle, Input, Vec2}; /// The vertical wheel scroll this frame that zooms, in points, read from the raw wheel events so /// each notch zooms by its whole step at once, as in standard CAD (#660). egui's smoothed delta @@ -26,18 +26,20 @@ pub(super) fn wheel_zoom_points(events: &[egui::Event], opts: &egui::InputOption } /// The model space tiles on screen (none without tiling): each tile's rectangle in `full`. -/// Open Edit Text on the text, mtext or attribute definition at `p` (the objects the shortcut -/// menu offers Edit Text for); false when there is none. +/// Start TEXTEDIT on the text, mtext or attribute definition at `p` (the objects its shortcut menu +/// offers Edit Text for); false when there is none. pub(super) fn edit_text_at(app: &mut CadApp, p: Vec2) -> bool { use cadcraft_engine::doc::EntityKind; - let hit = cadcraft_engine::cmd::curves::pick_at(&app.session, p).and_then(|h| { - let e = app.session.doc().ok()?.entity(h)?; - matches!(e.kind, EntityKind::Text(_) | EntityKind::MText(_) | EntityKind::AttDef(_)).then_some(h) + let is_text = cadcraft_engine::cmd::curves::pick_at(&app.session, p).and_then(|h| { + app.session.doc().ok()?.entity(h).map(|e| matches!(e.kind, EntityKind::Text(_) | EntityKind::MText(_) | EntityKind::AttDef(_))) }); - let Some(h) = hit else { return false }; - // The window edits the object in place of the command line, which used to take the caret and - // hide the drawing behind it. - app.ui.dialog = Some(format!("textedit:{}", h.hex())); + if is_text != Some(true) { + return false; + } + app.start("textedit"); + if let Err(e) = app.session.input(Input::Point(p)) { + app.session.echo(e.to_string()); + } true } diff --git a/crates/ui-egui/src/context_menu.rs b/crates/ui-egui/src/context_menu.rs index bbaf48df3..0b00d933c 100644 --- a/crates/ui-egui/src/context_menu.rs +++ b/crates/ui-egui/src/context_menu.rs @@ -153,9 +153,35 @@ fn object_commands(app: &CadApp) -> Vec<(&'static str, Option<&'static str>)> { } } -/// [`object_commands`] that are registered, as menu items. +/// [`object_commands`] that are registered, as menu items. The Edit Text entry of a single +/// selected text, mtext or attribute definition opens the Edit Text window instead of the +/// TEXTEDIT command line; the double-click keeps its in-place editing (#842), and several +/// selected texts still take the command line. pub fn object_entries(app: &CadApp) -> Vec { - object_commands(app).into_iter().filter_map(|(id, label)| item(app, id, label)).collect() + object_commands(app) + .into_iter() + .filter_map(|(id, label)| { + if id == "textedit" { + edit_text_window_entry(app).or_else(|| item(app, id, label)) + } else { + item(app, id, label) + } + }) + .collect() +} + +/// The Edit Text entry as the `textedit:` dialog id, for a single selected text, mtext +/// or attribute definition; `None` otherwise, so the command line entry stands in. +fn edit_text_window_entry(app: &CadApp) -> Option { + use cadcraft_engine::doc::EntityKind; + let sel = app.session.selection(); + if sel.len() != 1 { + return None; + } + let h = *sel.first()?; + let d = app.session.doc().ok()?; + d.entity(h).filter(|e| matches!(e.kind, EntityKind::Text(_) | EntityKind::MText(_) | EntityKind::AttDef(_)))?; + Some(Entry::Item { label: "Edit Text".into(), id: format!("textedit:{}", h.hex()), shortcut: None, enabled: true }) } /// The command menu while a command runs (`None` when none does): Enter and Cancel, Recent Input, @@ -213,6 +239,9 @@ pub fn choose(app: &mut CadApp, id: &str) { } } else if let Some(s) = id.strip_prefix(SNAP) { choose_snap(app, s); + } else if id.starts_with("textedit:") { + // The Edit Text window of the single selected text object; the id carries the handle. + app.ui.dialog = Some(id.to_string()); } else { activate(app, id); } diff --git a/crates/ui-egui/src/i18n/ar.tsv b/crates/ui-egui/src/i18n/ar.tsv index 657ec3fd1..75538130a 100644 --- a/crates/ui-egui/src/i18n/ar.tsv +++ b/crates/ui-egui/src/i18n/ar.tsv @@ -1374,3 +1374,4 @@ menu View عرض {command} is an unknown command. {command} أمر غير معروف. Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. تغيّر الرسم. أغلق النافذة وافتحها مرة أخرى. diff --git a/crates/ui-egui/src/i18n/bs.tsv b/crates/ui-egui/src/i18n/bs.tsv index 508fd7422..f2ee28566 100644 --- a/crates/ui-egui/src/i18n/bs.tsv +++ b/crates/ui-egui/src/i18n/bs.tsv @@ -1450,3 +1450,4 @@ menu Modify Izmijeni Associate Poveži Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. Crtež se promijenio. Zatvorite prozor i otvorite ga ponovo. diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index 1d5db0700..422b0a1b7 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -1230,3 +1230,4 @@ menu Modify Modifikace Could not check for updates. Aktualizace se nepodařilo zkontrolovat. Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. Výkres se změnil. Zavřete okno a otevřete jej znovu. diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index 213aa4f5a..cf1be2ca0 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -1047,3 +1047,4 @@ Could not check for updates. Die Suche nach Updates ist fehlgeschlagen. Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. Die Zeichnung hat sich geändert. Schließen Sie das Fenster und öffnen Sie es erneut. diff --git a/crates/ui-egui/src/i18n/el.tsv b/crates/ui-egui/src/i18n/el.tsv index 9a1b0784d..981a3054f 100644 --- a/crates/ui-egui/src/i18n/el.tsv +++ b/crates/ui-egui/src/i18n/el.tsv @@ -1341,3 +1341,4 @@ menu View Προβολή Could not check for updates. Δεν ήταν δυνατός ο έλεγχος για ενημερώσεις. Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. Το σχέδιο άλλαξε. Κλείστε το παράθυρο και ανοίξτε το ξανά. diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv index e02790314..16e8ce57d 100644 --- a/crates/ui-egui/src/i18n/es.tsv +++ b/crates/ui-egui/src/i18n/es.tsv @@ -1261,3 +1261,4 @@ Could not check for updates. No se pudo buscar actualizaciones. Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. El dibujo cambió. Cierre la ventana y ábrala de nuevo. diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv index 031519a07..d53fbd216 100644 --- a/crates/ui-egui/src/i18n/fr.tsv +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -1020,3 +1020,4 @@ Could not check for updates. Impossible de rechercher les mises à jour. Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. Le dessin a changé. Fermez la fenêtre et rouvrez-la. diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv index cd47b5ca6..c40c4b898 100644 --- a/crates/ui-egui/src/i18n/hu.tsv +++ b/crates/ui-egui/src/i18n/hu.tsv @@ -1352,3 +1352,4 @@ menu View Nézet Could not check for updates. A frissítések keresése nem sikerült. Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. A rajz megváltozott. Zárja be az ablakot, és nyissa meg újra. diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv index 550e3aeae..485790efa 100644 --- a/crates/ui-egui/src/i18n/it.tsv +++ b/crates/ui-egui/src/i18n/it.tsv @@ -1370,3 +1370,4 @@ menu Modify Edita Could not check for updates. Impossibile verificare gli aggiornamenti. Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. Il disegno è cambiato. Chiudere la finestra e riaprirla. diff --git a/crates/ui-egui/src/i18n/ko.tsv b/crates/ui-egui/src/i18n/ko.tsv index 847c78149..166e42c4f 100644 --- a/crates/ui-egui/src/i18n/ko.tsv +++ b/crates/ui-egui/src/i18n/ko.tsv @@ -1250,3 +1250,4 @@ menu Modify 수정 Could not check for updates. 업데이트를 확인하지 못했습니다. Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. 도면이 변경되었습니다. 창을 닫고 다시 여십시오. diff --git a/crates/ui-egui/src/i18n/pt_br.tsv b/crates/ui-egui/src/i18n/pt_br.tsv index 0e272cced..6fa9d6b45 100644 --- a/crates/ui-egui/src/i18n/pt_br.tsv +++ b/crates/ui-egui/src/i18n/pt_br.tsv @@ -1259,3 +1259,4 @@ Could not check for updates. Não foi possível verificar atualizações. Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. O desenho mudou. Feche a janela e abra-a novamente. diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index 3bcdb5aa7..4407bb82e 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -1021,3 +1021,4 @@ Could not check for updates. Не удалось проверить обновления. Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. Чертёж изменился. Закройте окно и откройте его снова. diff --git a/crates/ui-egui/src/i18n/sv.tsv b/crates/ui-egui/src/i18n/sv.tsv index bd5b8d59e..54c609d64 100644 --- a/crates/ui-egui/src/i18n/sv.tsv +++ b/crates/ui-egui/src/i18n/sv.tsv @@ -1454,3 +1454,4 @@ menu Modify Ändra Could not check for updates. Det gick inte att söka efter uppdateringar. Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. Ritningen har ändrats. Stäng fönstret och öppna det igen. diff --git a/crates/ui-egui/src/i18n/tr.tsv b/crates/ui-egui/src/i18n/tr.tsv index 2ad0e4a72..c002c60ba 100644 --- a/crates/ui-egui/src/i18n/tr.tsv +++ b/crates/ui-egui/src/i18n/tr.tsv @@ -1355,3 +1355,4 @@ menu View Görünüm Could not check for updates. Güncellemeler denetlenemedi. Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. Çizim değişti. Pencereyi kapatıp yeniden açın. diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index 10edda9a5..8c9d18b57 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -1379,3 +1379,4 @@ Save changes to block "{name}"? Зберегти зміни в блоці «{name}»? Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. Креслення змінилося. Закрийте вікно та відкрийте його знову. diff --git a/crates/ui-egui/src/i18n/vi.tsv b/crates/ui-egui/src/i18n/vi.tsv index 195616277..8908bb7ad 100644 --- a/crates/ui-egui/src/i18n/vi.tsv +++ b/crates/ui-egui/src/i18n/vi.tsv @@ -1454,3 +1454,4 @@ menu Modify Hiệu chỉnh Save Layout as Template Lưu layout thành mẫu Ctrl+Enter to apply Ctrl+Enter to apply Edit Text Edit Text + The drawing changed. Close the window and open it again. Bản vẽ đã thay đổi. Đóng cửa sổ và mở lại. diff --git a/crates/ui-egui/src/i18n/zh.tsv b/crates/ui-egui/src/i18n/zh.tsv index 8656cd4cf..d410b37de 100644 --- a/crates/ui-egui/src/i18n/zh.tsv +++ b/crates/ui-egui/src/i18n/zh.tsv @@ -1383,3 +1383,4 @@ Units 单位 Ctrl+Enter to apply Ctrl+Enter 应用 Edit Text 编辑文字 + The drawing changed. Close the window and open it again. 图纸已切换。请关闭窗口后重新打开。 diff --git a/crates/ui-egui/src/textdlg.rs b/crates/ui-egui/src/textdlg.rs index b3d13ae9f..c9a279660 100644 --- a/crates/ui-egui/src/textdlg.rs +++ b/crates/ui-egui/src/textdlg.rs @@ -1,10 +1,11 @@ -//! Edit Text: the window a double-click on a text object opens. +//! Edit Text: the window behind the shortcut menu's Edit Text entry. //! -//! TEXTEDIT already existed, but only as a command line: double-clicking a single-line text put -//! the caret in the command bar, one line, no context, and the text under the cursor was out of -//! sight. The window shows the same edit over the drawing: the object's own text, its type and -//! handle, and OK/Cancel. The engine call is unchanged (`textedit` with a handle and the new -//! text), so undo, locked layers and the DXF round trip behave exactly as before. +//! TEXTEDIT already existed, but only as a command line: it put the caret in the command bar, +//! one line, no context, and the text under the cursor was out of sight. The window shows the +//! same edit over the drawing: the object's own text, its type and handle, and OK/Cancel. The +//! engine call is unchanged (`textedit` with a handle and the new text), so undo, locked layers +//! and the DXF round trip behave exactly as before. The double-click keeps its in-place editing +//! (#842); the window is the shortcut menu's way in. use egui::RichText; use serde_json::json; @@ -33,13 +34,17 @@ struct State { text: String, /// What the drawing holds now, to tell an edit from a no-op. original: String, + /// The drawing the window was opened for: a handle means nothing once another drawing is + /// active, and committing to it would edit an object the user never saw. + uid: u64, message: String, } /// Read the object the window is for. A handle that no longer exists, or an object that is not /// text, leaves the window empty instead of failing: the drawing may have changed under it. fn initial(app: &CadApp, hex: &str) -> State { - let mut st = State { handle: hex.to_string(), ..Default::default() }; + let uid = app.session.state().map(|s| s.uid).unwrap_or_default(); + let mut st = State { handle: hex.to_string(), uid, ..Default::default() }; let Some(h) = cadcraft_doc::Handle::parse_hex(hex) else { return st }; let Ok(d) = app.session.doc() else { return st }; let Some(e) = d.entity(h) else { return st }; @@ -100,6 +105,11 @@ pub fn dialog(app: &mut CadApp, ctx: &egui::Context, spec: &str, open: &mut bool // keeps the undo stack honest. if st.text == st.original { keep = false; + } else if app.session.state().map(|s| s.uid).ok() != Some(st.uid) { + // The drawing switched while the window sat open: the handle now names another + // drawing's object, so the commit is refused and the user reopens on the drawing + // they meant to edit. + st.message = crate::tl!("The drawing changed. Close the window and open it again.").to_string(); } else { let params = json!({ "handles": [st.handle.clone()], "text": st.text }); match app.run("textedit", params) { @@ -112,5 +122,11 @@ pub fn dialog(app: &mut CadApp, ctx: &egui::Context, spec: &str, open: &mut bool } } *open = keep; - ctx.data_mut(|d| d.insert_temp(sid, st)); + // The state lives exactly as long as the window does: a closed window leaves nothing + // behind, so reopening it reads the drawing's text instead of an edit the user cancelled. + if keep { + ctx.data_mut(|d| d.insert_temp(sid, st)); + } else { + ctx.data_mut(|d| d.remove_temp::(sid)); + } }