From 1e93b16911bd38f6f7d3ce67b0682fed6162f415 Mon Sep 17 00:00:00 2001 From: ramox81 <184937705+ramox81@users.noreply.github.com> Date: Wed, 14 Oct 2026 13:27:44 +0300 Subject: [PATCH 1/2] Selection: report what each pick found while a command gathers objects Every pick during object selection prints the reference's count line: "N found" for the first pick or a pick that adds nothing, "N found, M total" after it, "N found, N removed, M total" when objects leave the set. It is printed before a command's own filtering, so "N were filtered out" follows it. COUNT reports through it and the ad hoc "object(s) found." / "object(s) added to selection." lines are gone. Co-Authored-By: Claude Opus 5.5 --- locales/ar-SA/opencadstudio.ftl | 3 +++ locales/bg-BG/opencadstudio.ftl | 3 +++ locales/cs-CZ/opencadstudio.ftl | 3 +++ locales/de-DE/opencadstudio.ftl | 3 +++ locales/el-GR/opencadstudio.ftl | 3 +++ locales/en-US/opencadstudio.ftl | 3 +++ locales/es-ES/opencadstudio.ftl | 3 +++ locales/fi-FI/opencadstudio.ftl | 3 +++ locales/fr-FR/opencadstudio.ftl | 3 +++ locales/hi-IN/opencadstudio.ftl | 3 +++ locales/hu-HU/opencadstudio.ftl | 3 +++ locales/it-IT/opencadstudio.ftl | 3 +++ locales/ja-JP/opencadstudio.ftl | 3 +++ locales/ko-KR/opencadstudio.ftl | 3 +++ locales/lo-LA/opencadstudio.ftl | 3 +++ locales/nl-NL/opencadstudio.ftl | 3 +++ locales/pl-PL/opencadstudio.ftl | 3 +++ locales/pt-BR/opencadstudio.ftl | 3 +++ locales/ru-RU/opencadstudio.ftl | 3 +++ locales/tr-TR/opencadstudio.ftl | 3 +++ locales/zh-CN/opencadstudio.ftl | 3 +++ locales/zh-TW/opencadstudio.ftl | 3 +++ src/app/command_driver/mod.rs | 3 --- src/app/command_driver/utilities.rs | 41 ++++++++++++++++++++++++++--- src/app/mod.rs | 4 +++ src/locale_catalog.rs | 1 + src/modules/annotate/count_cmd.rs | 13 +++------ 27 files changed, 112 insertions(+), 16 deletions(-) diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index 58d54f9a0..f4ff0f0a3 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -6553,3 +6553,6 @@ keytips = .hint-tabs = اكتب حرف علامة التبويب · Esc للإغلاق .hint-tab = علامة التبويب { $tab } · Esc للرجوع مستوى واحدًا .hint-items = اكتب حرف العنصر · Esc للرجوع مستوى واحدًا + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index acb1ac860..aa8beca95 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -6541,3 +6541,6 @@ keytips = .hint-tabs = Въведете буква на раздел · Esc затваря .hint-tab = Раздел { $tab } · Esc връща едно ниво назад .hint-items = Въведете буква на елемент · Esc връща едно ниво назад + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index c6f6151c8..a63286bf0 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -6538,3 +6538,6 @@ keytips = .hint-tabs = Zadejte písmeno karty · Esc zavře .hint-tab = Karta { $tab } · Esc o úroveň zpět .hint-items = Zadejte písmeno položky · Esc o úroveň zpět + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index 9686e0aaf..2c12ba126 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -6539,3 +6539,6 @@ keytips = .hint-tabs = Buchstaben einer Registerkarte eingeben · Esc schließt .hint-tab = Registerkarte { $tab } · Esc geht eine Ebene zurück .hint-items = Buchstaben eines Elements eingeben · Esc geht eine Ebene zurück + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/el-GR/opencadstudio.ftl b/locales/el-GR/opencadstudio.ftl index 26eca339a..c96b69705 100644 --- a/locales/el-GR/opencadstudio.ftl +++ b/locales/el-GR/opencadstudio.ftl @@ -6541,3 +6541,6 @@ keytips = .hint-tabs = Πληκτρολογήστε γράμμα καρτέλας · Το Esc κλείνει .hint-tab = Καρτέλα { $tab } · Το Esc επιστρέφει ένα επίπεδο .hint-items = Πληκτρολογήστε γράμμα στοιχείου · Το Esc επιστρέφει ένα επίπεδο + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index 0f4734280..42ecf310e 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -6540,3 +6540,6 @@ keytips = .hint-tabs = Type a tab letter · Esc closes .hint-tab = { $tab } tab · Esc goes back one level .hint-items = Type an item letter · Esc goes back one level + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index 4ae2ed045..7f9e4c023 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -6541,3 +6541,6 @@ keytips = .hint-tabs = Escriba la letra de una ficha · Esc cierra .hint-tab = Ficha { $tab } · Esc retrocede un nivel .hint-items = Escriba la letra de un elemento · Esc retrocede un nivel + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index 950164de4..4bbb005e7 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -6538,3 +6538,6 @@ keytips = .hint-tabs = Kirjoita välilehden kirjain · Esc sulkee .hint-tab = Välilehti { $tab } · Esc palaa tason taaksepäin .hint-items = Kirjoita kohteen kirjain · Esc palaa tason taaksepäin + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index 8b24070bd..b2ff82e85 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -6541,3 +6541,6 @@ keytips = .hint-tabs = Tapez la lettre d'un onglet · Échap ferme .hint-tab = Onglet { $tab } · Échap remonte d'un niveau .hint-items = Tapez la lettre d'un élément · Échap remonte d'un niveau + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index 0aab05d14..477a83872 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -6529,3 +6529,6 @@ keytips = .hint-tabs = टैब का अक्षर टाइप करें · Esc बंद करता है .hint-tab = { $tab } टैब · Esc एक स्तर पीछे जाता है .hint-items = आइटम का अक्षर टाइप करें · Esc एक स्तर पीछे जाता है + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index 4565836cd..b88ce6b77 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -6525,3 +6525,6 @@ keytips = .hint-tabs = Írja be a lap betűjét · Az Esc bezár .hint-tab = { $tab } lap · Az Esc egy szinttel visszalép .hint-items = Írja be az elem betűjét · Az Esc egy szinttel visszalép + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index 9f8ace95c..2c6a589a3 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -6540,3 +6540,6 @@ keytips = .hint-tabs = Digitare la lettera di una scheda · Esc chiude .hint-tab = Scheda { $tab } · Esc torna indietro di un livello .hint-items = Digitare la lettera di un elemento · Esc torna indietro di un livello + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index 6703c8b44..52ee886f4 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -6529,3 +6529,6 @@ keytips = .hint-tabs = タブの文字を入力 · Esc で閉じる .hint-tab = { $tab } タブ · Esc で 1 つ上に戻る .hint-items = 項目の文字を入力 · Esc で 1 つ上に戻る + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index b9bf8d88f..93150ff24 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -6540,3 +6540,6 @@ keytips = .hint-tabs = 탭 문자를 입력하십시오 · Esc로 닫기 .hint-tab = { $tab } 탭 · Esc로 한 단계 뒤로 .hint-items = 항목 문자를 입력하십시오 · Esc로 한 단계 뒤로 + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/lo-LA/opencadstudio.ftl b/locales/lo-LA/opencadstudio.ftl index 3fc078836..d479fd4f1 100644 --- a/locales/lo-LA/opencadstudio.ftl +++ b/locales/lo-LA/opencadstudio.ftl @@ -6541,3 +6541,6 @@ keytips = .hint-tabs = ພິມຕົວອັກສອນແຖບ · Esc ປິດ .hint-tab = ແຖບ { $tab } · Esc ກັບຄືນໜຶ່ງລະດັບ .hint-items = ພິມຕົວອັກສອນລາຍການ · Esc ກັບຄືນໜຶ່ງລະດັບ + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index 1aba8d7c3..4ebed33df 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -6539,3 +6539,6 @@ keytips = .hint-tabs = Typ de letter van een tabblad · Esc sluit .hint-tab = Tabblad { $tab } · Esc gaat één niveau terug .hint-items = Typ de letter van een item · Esc gaat één niveau terug + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index 0aa504dcc..393cebca8 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -6540,3 +6540,6 @@ keytips = .hint-tabs = Wpisz literę karty · Esc zamyka .hint-tab = Karta { $tab } · Esc cofa o jeden poziom .hint-items = Wpisz literę elementu · Esc cofa o jeden poziom + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index d68f4385d..dfd5118b9 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -6541,3 +6541,6 @@ keytips = .hint-tabs = Digite a letra de uma guia · Esc fecha .hint-tab = Guia { $tab } · Esc volta um nível .hint-items = Digite a letra de um item · Esc volta um nível + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index 25f2d76cc..9dda6cce5 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -6542,3 +6542,6 @@ keytips = .hint-tabs = Введите букву вкладки · Esc закрывает .hint-tab = Вкладка { $tab } · Esc — на уровень назад .hint-items = Введите букву элемента · Esc — на уровень назад + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index da6152f3a..ad90e48dd 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -6462,3 +6462,6 @@ keytips = .hint-tabs = Sekme harfini yazın · Esc kapatır .hint-tab = { $tab } sekmesi · Esc bir düzey geri .hint-items = Öğe harfini yazın · Esc bir düzey geri + +selection-report = + .found-removed-total = __ocs_fmt_0__ bulundu, __ocs_fmt_1__ çıkarıldı, toplam __ocs_fmt_2__ diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index ea8690e95..b2e5c1a40 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -6524,3 +6524,6 @@ keytips = .hint-tabs = 键入选项卡字母 · Esc 关闭 .hint-tab = { $tab } 选项卡 · Esc 返回上一级 .hint-items = 键入项目字母 · Esc 返回上一级 + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index aa43eb0bf..69b096b43 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -6536,3 +6536,6 @@ keytips = .hint-tabs = 輸入索引標籤字母 · Esc 關閉 .hint-tab = { $tab } 索引標籤 · Esc 返回上一層 .hint-items = 輸入項目字母 · Esc 返回上一層 + +selection-report = + .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/src/app/command_driver/mod.rs b/src/app/command_driver/mod.rs index 62dc55ec2..35a1c3440 100644 --- a/src/app/command_driver/mod.rs +++ b/src/app/command_driver/mod.rs @@ -1261,9 +1261,6 @@ impl OpenCADStudio { .into_iter() .map(|(h, _)| h) .collect(); - let count = handles.len(); - self.command_line - .push_info(crate::tf!("{count} object(s) found.").as_ref()); self.feed_command(StepInput::SelectionComplete(selected)) } diff --git a/src/app/command_driver/utilities.rs b/src/app/command_driver/utilities.rs index 38e35314d..386607e4f 100644 --- a/src/app/command_driver/utilities.rs +++ b/src/app/command_driver/utilities.rs @@ -574,6 +574,40 @@ impl OpenCADStudio { StepInput::SelectionComplete(kept) } +/// What one pick added to (or removed from) a gathering selection, as the + /// reference words it: `N found`, `N found, M total`, `N found, N removed, + /// M total`. Returns the command's key while it gathers. + // ponytail: compares the whole selection before and after, so a pick of an + // already chosen object reads `0 found` (the reference says `1 found (1 + // duplicate)`); pass the pick's own objects through StepInput if needed. + fn report_selection_found(&mut self, input: &StepInput) -> Option { + let StepInput::SelectionComplete(handles) = input else { + return None; + }; + let command = self.tabs[self.active_tab].active_cmd.as_ref()?; + if !command.is_selection_gathering() { + return None; + } + let key = &**command as *const dyn crate::command::CadCommand as *const () as usize; + let previous: rustc_hash::FxHashSet = match &self.selection_report { + Some((k, previous)) if *k == key => previous.iter().copied().collect(), + _ => Default::default(), + }; + let now: rustc_hash::FxHashSet = handles.iter().copied().collect(); + let found = now.difference(&previous).count(); + let removed = previous.difference(&now).count(); + let total = now.len(); + let line = if removed > 0 { + crate::tf!("{removed} found, {removed} removed, {total} total") + } else if found == 0 || previous.is_empty() { + crate::tf!("{found} found") + } else { + crate::tf!("{found} found, {total} total") + }; + self.command_line.push_info(line.as_ref()); + Some(key) + } + /// `feed_command`, also reporting whether the step actually took the input. /// Only a `Text` token can come back unclaimed (`on_text_input` returning /// `None`), which is what lets the caller read it as something else — a @@ -582,6 +616,7 @@ impl OpenCADStudio { &mut self, input: StepInput, ) -> (Task, bool) { + let gathering = self.report_selection_found(&input); // A command that takes associative dimensions only keeps just those: // the rest leave the selection and the count of what went is reported, // as the reference does while gathering. @@ -589,6 +624,9 @@ impl OpenCADStudio { let input = self.filter_block_reference_selection(input); let input = self.filter_locked_point_cloud_selection(input); let input = self.filter_command_entity_selection(input); + if let (Some(key), StepInput::SelectionComplete(kept)) = (gathering, &input) { + self.selection_report = Some((key, kept.clone())); + } // XCLIP / CLIP learn which chosen references carry a clip already. { let i = self.active_tab; @@ -1045,12 +1083,9 @@ impl OpenCADStudio { ); return Some(Task::none()); } - let count = add.len(); for h in add { self.tabs[i].scene.select_entity(h, false); } - self.command_line - .push_info(crate::tf!("{count} object(s) added to selection.").as_ref()); self.refresh_properties(); let handles: Vec = self.tabs[i] .scene diff --git a/src/app/mod.rs b/src/app/mod.rs index cf794b80a..57a1183f2 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -796,6 +796,9 @@ pub(super) struct OpenCADStudio { block_freq: std::collections::HashMap, /// BLOCKMRULIST: how many recent blocks the palette keeps (0–100). pub(crate) block_mru_list: u8, + /// The selection the gathering command had after the last pick (keyed by + /// the command), for the `N found, M total` line. + pub(crate) selection_report: Option<(usize, Vec)>, /// The Edit Reference dialog's remembered settings. pub(crate) refedit_options: crate::app::settings::RefEditOptions, /// BLOCKREDEFINEMODE (0–2). @@ -4682,6 +4685,7 @@ impl OpenCADStudio { block_mru: Vec::new(), block_freq: std::collections::HashMap::new(), block_mru_list: 50, + selection_report: None, refedit_options: Default::default(), block_redefine_mode: 1, block_navigate: ".".to_string(), diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index 3d578321d..6ee081809 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -3,6 +3,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static str)> { match source { + "{removed} found, {removed} removed, {total} total" => Some(("selection-report", "found-removed-total")), "Add to Working Set" => Some(("ref-edit", "add-to-working-set")), "Remove from Working Set" => Some(("ref-edit", "remove-from-working-set")), "Select reference:" => Some(("ref-edit", "select-reference")), diff --git a/src/modules/annotate/count_cmd.rs b/src/modules/annotate/count_cmd.rs index dd1dba80c..8e9c295d9 100644 --- a/src/modules/annotate/count_cmd.rs +++ b/src/modules/annotate/count_cmd.rs @@ -158,17 +158,10 @@ impl CadCommand for CountCommand { } fn on_selection_complete(&mut self, handles: Vec) -> CmdResult { - // The selection arrives whole after every pick: `1 found`, then - // `1 found, 2 total`. - let found = handles.iter().filter(|h| !self.targets.contains(h)).count(); - let first = self.targets.is_empty(); + // The selection arrives whole after every pick; the driver reports + // what each pick found. self.targets = handles; - let total = self.targets.len(); - CmdResult::ReportMeasurement(if first { - crate::tf!("{found} found").into_owned() - } else { - crate::tf!("{found} found, {total} total").into_owned() - }) + CmdResult::NeedPoint } fn needs_entity_pick(&self) -> bool { From b9fd0a066cc56f39db8903f840f5cd31f71b04f5 Mon Sep 17 00:00:00 2001 From: ramox81 <184937705+ramox81@users.noreply.github.com> Date: Wed, 14 Oct 2026 14:49:27 +0300 Subject: [PATCH 2/2] Selection: count duplicates and removals from the step's own picks The count line now uses the objects the selection step itself picked (a click, a window or crossing, a lasso, a fence, Last / Previous / All): "N found (D duplicate), M total" when some were chosen already, "N found, R removed, M total" in remove mode, "N found, M total" when a removal picks objects that were not chosen. Co-Authored-By: Claude Opus 5.5 --- locales/ar-SA/opencadstudio.ftl | 1 + locales/bg-BG/opencadstudio.ftl | 1 + locales/cs-CZ/opencadstudio.ftl | 1 + locales/de-DE/opencadstudio.ftl | 1 + locales/el-GR/opencadstudio.ftl | 1 + locales/en-US/opencadstudio.ftl | 1 + locales/es-ES/opencadstudio.ftl | 1 + locales/fi-FI/opencadstudio.ftl | 1 + locales/fr-FR/opencadstudio.ftl | 1 + locales/hi-IN/opencadstudio.ftl | 1 + locales/hu-HU/opencadstudio.ftl | 1 + locales/it-IT/opencadstudio.ftl | 1 + locales/ja-JP/opencadstudio.ftl | 1 + locales/ko-KR/opencadstudio.ftl | 1 + locales/lo-LA/opencadstudio.ftl | 1 + locales/nl-NL/opencadstudio.ftl | 1 + locales/pl-PL/opencadstudio.ftl | 1 + locales/pt-BR/opencadstudio.ftl | 1 + locales/ru-RU/opencadstudio.ftl | 1 + locales/tr-TR/opencadstudio.ftl | 1 + locales/zh-CN/opencadstudio.ftl | 1 + locales/zh-TW/opencadstudio.ftl | 1 + src/app/command_driver/mod.rs | 1 + src/app/command_driver/utilities.rs | 39 +++++++++++++++++++++-------- src/app/mod.rs | 4 +++ src/app/update/viewport.rs | 14 +++++++++++ src/locale_catalog.rs | 3 ++- 27 files changed, 71 insertions(+), 12 deletions(-) diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index f4ff0f0a3..e84c5fd8f 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -6555,4 +6555,5 @@ keytips = .hint-items = اكتب حرف العنصر · Esc للرجوع مستوى واحدًا selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index aa8beca95..bcd5aab76 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -6543,4 +6543,5 @@ keytips = .hint-items = Въведете буква на елемент · Esc връща едно ниво назад selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index a63286bf0..24054b825 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -6540,4 +6540,5 @@ keytips = .hint-items = Zadejte písmeno položky · Esc o úroveň zpět selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index 2c12ba126..8d5c492e4 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -6541,4 +6541,5 @@ keytips = .hint-items = Buchstaben eines Elements eingeben · Esc geht eine Ebene zurück selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/el-GR/opencadstudio.ftl b/locales/el-GR/opencadstudio.ftl index c96b69705..83abcef0e 100644 --- a/locales/el-GR/opencadstudio.ftl +++ b/locales/el-GR/opencadstudio.ftl @@ -6543,4 +6543,5 @@ keytips = .hint-items = Πληκτρολογήστε γράμμα στοιχείου · Το Esc επιστρέφει ένα επίπεδο selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index 42ecf310e..d6146e862 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -6542,4 +6542,5 @@ keytips = .hint-items = Type an item letter · Esc goes back one level selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index 7f9e4c023..88297e132 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -6543,4 +6543,5 @@ keytips = .hint-items = Escriba la letra de un elemento · Esc retrocede un nivel selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index 4bbb005e7..c19f35ca8 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -6540,4 +6540,5 @@ keytips = .hint-items = Kirjoita kohteen kirjain · Esc palaa tason taaksepäin selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index b2ff82e85..01b10f57c 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -6543,4 +6543,5 @@ keytips = .hint-items = Tapez la lettre d'un élément · Échap remonte d'un niveau selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index 477a83872..fea3d7c76 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -6531,4 +6531,5 @@ keytips = .hint-items = आइटम का अक्षर टाइप करें · Esc एक स्तर पीछे जाता है selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index b88ce6b77..c52b06e1e 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -6527,4 +6527,5 @@ keytips = .hint-items = Írja be az elem betűjét · Az Esc egy szinttel visszalép selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index 2c6a589a3..e5447368e 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -6542,4 +6542,5 @@ keytips = .hint-items = Digitare la lettera di un elemento · Esc torna indietro di un livello selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index 52ee886f4..422b75f8b 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -6531,4 +6531,5 @@ keytips = .hint-items = 項目の文字を入力 · Esc で 1 つ上に戻る selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index 93150ff24..670d3fb14 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -6542,4 +6542,5 @@ keytips = .hint-items = 항목 문자를 입력하십시오 · Esc로 한 단계 뒤로 selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/lo-LA/opencadstudio.ftl b/locales/lo-LA/opencadstudio.ftl index d479fd4f1..620f07534 100644 --- a/locales/lo-LA/opencadstudio.ftl +++ b/locales/lo-LA/opencadstudio.ftl @@ -6543,4 +6543,5 @@ keytips = .hint-items = ພິມຕົວອັກສອນລາຍການ · Esc ກັບຄືນໜຶ່ງລະດັບ selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index 4ebed33df..376de9e6f 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -6541,4 +6541,5 @@ keytips = .hint-items = Typ de letter van een item · Esc gaat één niveau terug selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index 393cebca8..d5c96d838 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -6542,4 +6542,5 @@ keytips = .hint-items = Wpisz literę elementu · Esc cofa o jeden poziom selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index dfd5118b9..23410c3fe 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -6543,4 +6543,5 @@ keytips = .hint-items = Digite a letra de um item · Esc volta um nível selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index 9dda6cce5..62c73a644 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -6544,4 +6544,5 @@ keytips = .hint-items = Введите букву элемента · Esc — на уровень назад selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index ad90e48dd..10fb58b28 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -6464,4 +6464,5 @@ keytips = .hint-items = Öğe harfini yazın · Esc bir düzey geri selection-report = + .found-duplicate-total = __ocs_fmt_0__ bulundu (__ocs_fmt_1__ yinelenen), toplam __ocs_fmt_2__ .found-removed-total = __ocs_fmt_0__ bulundu, __ocs_fmt_1__ çıkarıldı, toplam __ocs_fmt_2__ diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index b2e5c1a40..771251db3 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -6526,4 +6526,5 @@ keytips = .hint-items = 键入项目字母 · Esc 返回上一级 selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index 69b096b43..970fba011 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -6538,4 +6538,5 @@ keytips = .hint-items = 輸入項目字母 · Esc 返回上一層 selection-report = + .found-duplicate-total = __ocs_fmt_0__ found (__ocs_fmt_1__ duplicate), __ocs_fmt_2__ total .found-removed-total = __ocs_fmt_0__ found, __ocs_fmt_1__ removed, __ocs_fmt_2__ total diff --git a/src/app/command_driver/mod.rs b/src/app/command_driver/mod.rs index 35a1c3440..652fdc623 100644 --- a/src/app/command_driver/mod.rs +++ b/src/app/command_driver/mod.rs @@ -1244,6 +1244,7 @@ impl OpenCADStudio { bounds, |point| self.cursor_model_point(i, &edit_cam, point, bounds), ); + self.last_pick = Some((handles.clone(), self.select_remove_mode)); if self.select_remove_mode { for h in &handles { self.tabs[i].scene.deselect_entity(*h); diff --git a/src/app/command_driver/utilities.rs b/src/app/command_driver/utilities.rs index 386607e4f..8410745ad 100644 --- a/src/app/command_driver/utilities.rs +++ b/src/app/command_driver/utilities.rs @@ -574,16 +574,16 @@ impl OpenCADStudio { StepInput::SelectionComplete(kept) } -/// What one pick added to (or removed from) a gathering selection, as the - /// reference words it: `N found`, `N found, M total`, `N found, N removed, - /// M total`. Returns the command's key while it gathers. - // ponytail: compares the whole selection before and after, so a pick of an - // already chosen object reads `0 found` (the reference says `1 found (1 - // duplicate)`); pass the pick's own objects through StepInput if needed. +/// What one selection step picked, as the reference words it: `N found` + /// for the first step, `N found, M total`, `N found (D duplicate), M + /// total` when some were chosen already, `N found, R removed, M total` in + /// remove mode. Returns the command's key while it gathers. fn report_selection_found(&mut self, input: &StepInput) -> Option { let StepInput::SelectionComplete(handles) = input else { return None; }; + // A pick belongs to this step only; never to a later one. + let last_pick = self.last_pick.take(); let command = self.tabs[self.active_tab].active_cmd.as_ref()?; if !command.is_selection_gathering() { return None; @@ -594,13 +594,29 @@ impl OpenCADStudio { _ => Default::default(), }; let now: rustc_hash::FxHashSet = handles.iter().copied().collect(); - let found = now.difference(&previous).count(); - let removed = previous.difference(&now).count(); let total = now.len(); - let line = if removed > 0 { - crate::tf!("{removed} found, {removed} removed, {total} total") - } else if found == 0 || previous.is_empty() { + // What the step picked: its own objects when the pick says so, else + // what the selection gained or lost. + let (picked, remove) = match last_pick { + Some((picked, remove)) => (picked.into_iter().collect(), remove), + None => { + let lost: rustc_hash::FxHashSet = + previous.difference(&now).copied().collect(); + if lost.is_empty() { + (now.difference(&previous).copied().collect(), false) + } else { + (lost, true) + } + } + }; + let found = picked.len(); + let known = picked.intersection(&previous).count(); + let line = if found == 0 || previous.is_empty() && !remove { crate::tf!("{found} found") + } else if remove && known > 0 { + crate::tf!("{found} found, {known} removed, {total} total") + } else if !remove && known > 0 { + crate::tf!("{found} found ({known} duplicate), {total} total") } else { crate::tf!("{found} found, {total} total") }; @@ -1083,6 +1099,7 @@ impl OpenCADStudio { ); return Some(Task::none()); } + self.last_pick = Some((add.clone(), false)); for h in add { self.tabs[i].scene.select_entity(h, false); } diff --git a/src/app/mod.rs b/src/app/mod.rs index 57a1183f2..84a6242fd 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -799,6 +799,9 @@ pub(super) struct OpenCADStudio { /// The selection the gathering command had after the last pick (keyed by /// the command), for the `N found, M total` line. pub(crate) selection_report: Option<(usize, Vec)>, + /// The objects the last selection step picked (a click, a window, a + /// fence, Last / Previous / All) and whether it removed them. + pub(crate) last_pick: Option<(Vec, bool)>, /// The Edit Reference dialog's remembered settings. pub(crate) refedit_options: crate::app::settings::RefEditOptions, /// BLOCKREDEFINEMODE (0–2). @@ -4686,6 +4689,7 @@ impl OpenCADStudio { block_freq: std::collections::HashMap::new(), block_mru_list: 50, selection_report: None, + last_pick: None, refedit_options: Default::default(), block_redefine_mode: 1, block_navigate: ".".to_string(), diff --git a/src/app/update/viewport.rs b/src/app/update/viewport.rs index 397be1f48..c60d8798b 100644 --- a/src/app/update/viewport.rs +++ b/src/app/update/viewport.rs @@ -5215,6 +5215,10 @@ properties={:.1}ms picked={}", // lasso adds, Shift+lasso removes. An empty lasso // leaves the current selection untouched so a stray // drag never discards hard-won picks. + if is_gathering { + self.last_pick = + Some((handles.clone(), self.shift_down || self.select_remove_mode)); + } if self.shift_down || self.select_remove_mode { self.tabs[i].scene.deselect_entities(&handles); } else { @@ -5356,6 +5360,12 @@ properties={:.1}ms picked={}", let hit = hit.filter(|&h| self.tabs[i].scene.passes_selection_filter(h)); if let Some(handle) = hit { + if is_gathering { + self.last_pick = Some(( + vec![handle], + self.shift_down || self.select_remove_mode, + )); + } // Individual picks accumulate (issue #47): // each plain click adds to the selection, // Shift+click removes the picked entity. @@ -5488,6 +5498,10 @@ was_selected={}", // entities. An empty box leaves the selection alone // so an accidental empty drag never discards it. // PICKADD 0 (#226): a plain box REPLACES instead. + if is_gathering { + self.last_pick = + Some((handles.clone(), self.shift_down || self.select_remove_mode)); + } if self.shift_down || self.select_remove_mode { self.tabs[i].scene.deselect_entities(&handles); } else { diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index 6ee081809..3305e4bf4 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -3,7 +3,8 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static str)> { match source { - "{removed} found, {removed} removed, {total} total" => Some(("selection-report", "found-removed-total")), + "{found} found, {known} removed, {total} total" => Some(("selection-report", "found-removed-total")), + "{found} found ({known} duplicate), {total} total" => Some(("selection-report", "found-duplicate-total")), "Add to Working Set" => Some(("ref-edit", "add-to-working-set")), "Remove from Working Set" => Some(("ref-edit", "remove-from-working-set")), "Select reference:" => Some(("ref-edit", "select-reference")),