From 1d78ab25746b5ee0d285cb198694366a80bba373 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Tue, 6 Oct 2026 09:33:08 +0300 Subject: [PATCH] fix(count): invalid-area restore, honest UPDATEFIELD, i18n and SVG icons - Invalid Area "Undo" reverts the step that lost the boundary (redo after an undo, undo otherwise), checks the boundary is back and otherwise puts the step back and continues without the area; no auto-undo loop. - COUNTCLOSE / area replacement remove the count polyline outside the history instead of as an undo step of their own. - UPDATEFIELD re-evaluates the field texts of a table's *T block and reports the number actually updated. - Zoom to a counted object goes through the f64 handle_zoom_to_window. - Palette: SVG icons instead of glyph text, list cache keyed by tab id, cached result borrowed instead of cloned, "Count" as the source text. - Command-line messages go through t!/tf! with entries in all locales. - Cleanups: \n escapes, area comment, unused parameter, comment order. Co-Authored-By: Claude Opus 5.5 --- assets/icons/ui/info.svg | 1 + assets/icons/ui/more.svg | 1 + locales/ar-SA/opencadstudio.ftl | 17 +++- locales/bg-BG/opencadstudio.ftl | 17 +++- locales/cs-CZ/opencadstudio.ftl | 17 +++- locales/de-DE/opencadstudio.ftl | 17 +++- locales/el-GR/opencadstudio.ftl | 17 +++- locales/en-US/opencadstudio.ftl | 17 +++- locales/es-ES/opencadstudio.ftl | 17 +++- locales/fi-FI/opencadstudio.ftl | 17 +++- locales/fr-FR/opencadstudio.ftl | 17 +++- locales/hi-IN/opencadstudio.ftl | 17 +++- locales/hu-HU/opencadstudio.ftl | 17 +++- locales/it-IT/opencadstudio.ftl | 17 +++- locales/ja-JP/opencadstudio.ftl | 17 +++- locales/ko-KR/opencadstudio.ftl | 17 +++- locales/nl-NL/opencadstudio.ftl | 17 +++- locales/pl-PL/opencadstudio.ftl | 17 +++- locales/pt-BR/opencadstudio.ftl | 17 +++- locales/ru-RU/opencadstudio.ftl | 17 +++- locales/tr-TR/opencadstudio.ftl | 17 +++- locales/zh-CN/opencadstudio.ftl | 17 +++- locales/zh-TW/opencadstudio.ftl | 17 +++- src/app/command_driver/viewport.rs | 2 +- src/app/commands/count.rs | 147 ++++++++++++++++++----------- src/app/control/actions.rs | 4 +- src/app/view/mod.rs | 1 + src/locale_catalog.rs | 17 +++- src/modules/annotate/count_cmd.rs | 38 ++++---- src/modules/view/count_palette.rs | 2 +- src/ui/icons.rs | 2 + src/ui/popup/context_menu.rs | 2 +- src/ui/window/count_palette.rs | 53 +++++------ 33 files changed, 476 insertions(+), 151 deletions(-) create mode 100644 assets/icons/ui/info.svg create mode 100644 assets/icons/ui/more.svg diff --git a/assets/icons/ui/info.svg b/assets/icons/ui/info.svg new file mode 100644 index 000000000..212f70fce --- /dev/null +++ b/assets/icons/ui/info.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/ui/more.svg b/assets/icons/ui/more.svg new file mode 100644 index 000000000..50d01007a --- /dev/null +++ b/assets/icons/ui/more.svg @@ -0,0 +1 @@ + diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index a39edaf12..1c01174f9 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -5940,8 +5940,6 @@ style-manager = .block-extents = نطاق الكتلة .base-point = نقطة الأساس count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5964,3 +5962,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = تم العثور على __ocs_fmt_0__ + .found-total = تم العثور على __ocs_fmt_0__، الإجمالي __ocs_fmt_1__ + .field-only-in-count = ** الأمر COUNTFIELD متاح فقط أثناء العد. ** + .area-active = منطقة العد نشطة. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (للقراءة فقط) + .requires-0-or-1 = يتطلب 0 أو 1 فقط. + .requires-int-range = يتطلب عددًا صحيحًا بين __ocs_fmt_0__ و __ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT نمط النص الحالي: "__ocs_fmt_0__" ارتفاع النص: __ocs_fmt_1__ + .fields-found = تم العثور على __ocs_fmt_0__ من الحقول. + .fields-updated = تم تحديث __ocs_fmt_0__ من الحقول. + .invalid-keyword = كلمة مفتاحية للخيار غير صالحة. + .invalid-boundary = كائن حد منطقة العد غير صالح. حدد خطًا متعددًا مغلقًا يتكون من قطع مستقيمة ولا يتقاطع مع نفسه. + .block-not-found = تعذر العثور على الكتلة "__ocs_fmt_0__". + .invalid-point = نقطة غير صالحة. diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index 294ebfdf2..fe2b0bf6c 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -5928,8 +5928,6 @@ style-manager = .block-extents = Обхват на блок .base-point = Базова точка count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5952,3 +5950,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = Намерени: __ocs_fmt_0__ + .found-total = Намерени: __ocs_fmt_0__, общо: __ocs_fmt_1__ + .field-only-in-count = ** Командата COUNTFIELD е достъпна само по време на преброяване. ** + .area-active = Областта за преброяване е активна. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (само за четене) + .requires-0-or-1 = Изисква се само 0 или 1. + .requires-int-range = Изисква се цяло число между __ocs_fmt_0__ и __ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Текущ текстов стил: "__ocs_fmt_0__" Височина на текста: __ocs_fmt_1__ + .fields-found = Намерени полета: __ocs_fmt_0__. + .fields-updated = Обновени полета: __ocs_fmt_0__. + .invalid-keyword = Невалидна ключова дума на опция. + .invalid-boundary = Невалиден обект за граница на областта за преброяване. Изберете затворена полилиния от отсечки, която не се самопресича. + .block-not-found = Блокът "__ocs_fmt_0__" не може да бъде намерен. + .invalid-point = Невалидна точка. diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index b26dfe485..10cc0a116 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -5925,8 +5925,6 @@ style-manager = .block-extents = Blokovat rozsahy .base-point = Základní bod count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5949,3 +5947,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = Nalezeno: __ocs_fmt_0__ + .found-total = Nalezeno: __ocs_fmt_0__, celkem: __ocs_fmt_1__ + .field-only-in-count = ** Příkaz COUNTFIELD je dostupný pouze během počítání. ** + .area-active = Oblast počítání je aktivní. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (jen pro čtení) + .requires-0-or-1 = Vyžaduje pouze 0 nebo 1. + .requires-int-range = Vyžaduje celé číslo mezi __ocs_fmt_0__ a __ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Aktuální styl textu: "__ocs_fmt_0__" Výška textu: __ocs_fmt_1__ + .fields-found = Nalezeno polí: __ocs_fmt_0__. + .fields-updated = Aktualizováno polí: __ocs_fmt_0__. + .invalid-keyword = Neplatné klíčové slovo volby. + .invalid-boundary = Neplatný objekt hranice oblasti počítání. Vyberte uzavřenou křivku složenou z úseček, která neprotíná sama sebe. + .block-not-found = Blok "__ocs_fmt_0__" nelze najít. + .invalid-point = Neplatný bod. diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index 14e1ceaa3..605ccb174 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -5926,8 +5926,6 @@ style-manager = .block-extents = Blockgrenzen .base-point = Basispunkt count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5950,3 +5948,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = __ocs_fmt_0__ gefunden + .found-total = __ocs_fmt_0__ gefunden, __ocs_fmt_1__ gesamt + .field-only-in-count = ** Der Befehl COUNTFIELD ist nur während der Zählung verfügbar. ** + .area-active = Zählbereich ist aktiv. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (schreibgeschützt) + .requires-0-or-1 = Nur 0 oder 1 zulässig. + .requires-int-range = Erfordert eine ganze Zahl zwischen __ocs_fmt_0__ und __ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Aktueller Textstil: "__ocs_fmt_0__" Texthöhe: __ocs_fmt_1__ + .fields-found = __ocs_fmt_0__ Feld(er) gefunden. + .fields-updated = __ocs_fmt_0__ Feld(er) aktualisiert. + .invalid-keyword = Ungültiges Optionsschlüsselwort. + .invalid-boundary = Ungültiges Begrenzungsobjekt für den Zählbereich. Wählen Sie eine geschlossene Polylinie aus Liniensegmenten, die sich nicht selbst schneidet. + .block-not-found = Block "__ocs_fmt_0__" wurde nicht gefunden. + .invalid-point = Ungültiger Punkt. diff --git a/locales/el-GR/opencadstudio.ftl b/locales/el-GR/opencadstudio.ftl index 047ec281e..433624525 100644 --- a/locales/el-GR/opencadstudio.ftl +++ b/locales/el-GR/opencadstudio.ftl @@ -5928,8 +5928,6 @@ style-manager = .block-extents = Όρια μπλοκ .base-point = Σημείο βάσης count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5952,3 +5950,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = Βρέθηκαν: __ocs_fmt_0__ + .found-total = Βρέθηκαν: __ocs_fmt_0__, σύνολο: __ocs_fmt_1__ + .field-only-in-count = ** Η εντολή COUNTFIELD είναι διαθέσιμη μόνο κατά την καταμέτρηση. ** + .area-active = Η περιοχή καταμέτρησης είναι ενεργή. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (μόνο για ανάγνωση) + .requires-0-or-1 = Απαιτείται μόνο 0 ή 1. + .requires-int-range = Απαιτείται ακέραιος μεταξύ __ocs_fmt_0__ και __ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Τρέχον στυλ κειμένου: "__ocs_fmt_0__" Ύψος κειμένου: __ocs_fmt_1__ + .fields-found = Βρέθηκαν πεδία: __ocs_fmt_0__. + .fields-updated = Ενημερώθηκαν πεδία: __ocs_fmt_0__. + .invalid-keyword = Μη έγκυρη λέξη-κλειδί επιλογής. + .invalid-boundary = Μη έγκυρο αντικείμενο ορίου περιοχής καταμέτρησης. Επιλέξτε μια κλειστή πολυγραμμή από ευθύγραμμα τμήματα που δεν τέμνει τον εαυτό της. + .block-not-found = Το μπλοκ "__ocs_fmt_0__" δεν βρέθηκε. + .invalid-point = Μη έγκυρο σημείο. diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index 96e53825f..6f3f4730d 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -5929,8 +5929,6 @@ style-manager = .block-extents = Block extents .base-point = Base point count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5953,3 +5951,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = __ocs_fmt_0__ found + .found-total = __ocs_fmt_0__ found, __ocs_fmt_1__ total + .field-only-in-count = ** COUNTFIELD command only available during Count. ** + .area-active = count area is active. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (read only) + .requires-0-or-1 = Requires 0 or 1 only. + .requires-int-range = Requires an integer between __ocs_fmt_0__ and __ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Current text style: "__ocs_fmt_0__" Text height: __ocs_fmt_1__ + .fields-found = __ocs_fmt_0__ field(s) found. + .fields-updated = __ocs_fmt_0__ field(s) updated. + .invalid-keyword = Invalid option keyword. + .invalid-boundary = Invalid count area boundary object. Select a closed polyline consisting of line segments and does not intersect itself. + .block-not-found = Block "__ocs_fmt_0__" cannot be found. + .invalid-point = Invalid point. diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index 79a021096..4bb6669be 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -5928,8 +5928,6 @@ style-manager = .block-extents = Extensión del bloque .base-point = Punto base count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5952,3 +5950,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = __ocs_fmt_0__ encontrado(s) + .found-total = __ocs_fmt_0__ encontrado(s), __ocs_fmt_1__ en total + .field-only-in-count = ** El comando COUNTFIELD solo está disponible durante el recuento. ** + .area-active = El área de recuento está activa. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (solo lectura) + .requires-0-or-1 = Solo admite 0 o 1. + .requires-int-range = Se requiere un entero entre __ocs_fmt_0__ y __ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Estilo de texto actual: "__ocs_fmt_0__" Altura de texto: __ocs_fmt_1__ + .fields-found = __ocs_fmt_0__ campo(s) encontrado(s). + .fields-updated = __ocs_fmt_0__ campo(s) actualizado(s). + .invalid-keyword = Palabra clave de opción no válida. + .invalid-boundary = Objeto de contorno de área de recuento no válido. Seleccione una polilínea cerrada formada por segmentos de línea que no se corte a sí misma. + .block-not-found = No se encuentra el bloque "__ocs_fmt_0__". + .invalid-point = Punto no válido. diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index 72cbd4dcd..e01e8ffca 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -5925,8 +5925,6 @@ style-manager = .block-extents = Estä laajuudet .base-point = Peruspiste count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5949,3 +5947,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = Löytyi __ocs_fmt_0__ + .found-total = Löytyi __ocs_fmt_0__, yhteensä __ocs_fmt_1__ + .field-only-in-count = ** COUNTFIELD-komento on käytettävissä vain laskennan aikana. ** + .area-active = Laskenta-alue on aktiivinen. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (vain luku) + .requires-0-or-1 = Vain 0 tai 1 sallitaan. + .requires-int-range = Vaaditaan kokonaisluku väliltä __ocs_fmt_0__–__ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Nykyinen tekstityyli: "__ocs_fmt_0__" Tekstin korkeus: __ocs_fmt_1__ + .fields-found = Kenttiä löytyi: __ocs_fmt_0__. + .fields-updated = Kenttiä päivitetty: __ocs_fmt_0__. + .invalid-keyword = Virheellinen asetuksen avainsana. + .invalid-boundary = Virheellinen laskenta-alueen rajaobjekti. Valitse suljettu, janoista koostuva moniviiva, joka ei leikkaa itseään. + .block-not-found = Lohkoa "__ocs_fmt_0__" ei löydy. + .invalid-point = Virheellinen piste. diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index 702e42640..ca2bda963 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -5927,8 +5927,6 @@ style-manager = .block-extents = Limites du bloc .base-point = Point de base count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5951,3 +5949,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = __ocs_fmt_0__ trouvé(s) + .found-total = __ocs_fmt_0__ trouvé(s), __ocs_fmt_1__ au total + .field-only-in-count = ** La commande COUNTFIELD n'est disponible que pendant le comptage. ** + .area-active = La zone de comptage est active. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (lecture seule) + .requires-0-or-1 = Nécessite 0 ou 1 uniquement. + .requires-int-range = Nécessite un entier compris entre __ocs_fmt_0__ et __ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Style de texte courant : "__ocs_fmt_0__" Hauteur du texte : __ocs_fmt_1__ + .fields-found = __ocs_fmt_0__ champ(s) trouvé(s). + .fields-updated = __ocs_fmt_0__ champ(s) mis à jour. + .invalid-keyword = Mot-clé d'option non valide. + .invalid-boundary = Objet de contour de zone de comptage non valide. Sélectionnez une polyligne fermée composée de segments de ligne et qui ne se recoupe pas. + .block-not-found = Le bloc "__ocs_fmt_0__" est introuvable. + .invalid-point = Point non valide. diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index 0ab2cf7fa..3585bacf9 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -5916,8 +5916,6 @@ style-manager = .block-extents = ब्लॉक परिमिति .base-point = आधार बिंदु count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5940,3 +5938,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = __ocs_fmt_0__ मिले + .found-total = __ocs_fmt_0__ मिले, कुल __ocs_fmt_1__ + .field-only-in-count = ** COUNTFIELD कमांड केवल गणना के दौरान उपलब्ध है। ** + .area-active = गणना क्षेत्र सक्रिय है। + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (केवल पढ़ने के लिए) + .requires-0-or-1 = केवल 0 या 1 आवश्यक है। + .requires-int-range = __ocs_fmt_0__ और __ocs_fmt_1__ के बीच पूर्णांक आवश्यक है। + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT वर्तमान टेक्स्ट शैली: "__ocs_fmt_0__" टेक्स्ट ऊँचाई: __ocs_fmt_1__ + .fields-found = __ocs_fmt_0__ फ़ील्ड मिले। + .fields-updated = __ocs_fmt_0__ फ़ील्ड अपडेट किए गए। + .invalid-keyword = अमान्य विकल्प कीवर्ड। + .invalid-boundary = अमान्य गणना क्षेत्र सीमा ऑब्जेक्ट। रेखा खंडों से बनी ऐसी बंद पॉलीलाइन चुनें जो स्वयं को प्रतिच्छेद न करे। + .block-not-found = ब्लॉक "__ocs_fmt_0__" नहीं मिला। + .invalid-point = अमान्य बिंदु। diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index a92b034f2..665907146 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -5927,8 +5927,6 @@ style-manager = .block-extents = Kiterjedések blokkolása .base-point = Alappont count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5951,3 +5949,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = __ocs_fmt_0__ található + .found-total = __ocs_fmt_0__ található, összesen __ocs_fmt_1__ + .field-only-in-count = ** A COUNTFIELD parancs csak számlálás közben érhető el. ** + .area-active = A számlálási terület aktív. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (csak olvasható) + .requires-0-or-1 = Csak 0 vagy 1 adható meg. + .requires-int-range = __ocs_fmt_0__ és __ocs_fmt_1__ közötti egész szám szükséges. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Aktuális szövegstílus: "__ocs_fmt_0__" Szövegmagasság: __ocs_fmt_1__ + .fields-found = __ocs_fmt_0__ mező található. + .fields-updated = __ocs_fmt_0__ mező frissítve. + .invalid-keyword = Érvénytelen opciókulcsszó. + .invalid-boundary = Érvénytelen számlálási terület határobjektum. Válasszon egy zárt, vonalszakaszokból álló, önmagát nem metsző vonalláncot. + .block-not-found = A(z) "__ocs_fmt_0__" blokk nem található. + .invalid-point = Érvénytelen pont. diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index d4f900ae2..134de2c2b 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -5927,8 +5927,6 @@ style-manager = .block-extents = Blocca estensioni .base-point = Punto base count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5951,3 +5949,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = __ocs_fmt_0__ trovati + .found-total = __ocs_fmt_0__ trovati, __ocs_fmt_1__ in totale + .field-only-in-count = ** Il comando COUNTFIELD è disponibile solo durante il conteggio. ** + .area-active = L'area di conteggio è attiva. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (sola lettura) + .requires-0-or-1 = Richiede solo 0 o 1. + .requires-int-range = Richiede un numero intero compreso tra __ocs_fmt_0__ e __ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Stile di testo corrente: "__ocs_fmt_0__" Altezza testo: __ocs_fmt_1__ + .fields-found = __ocs_fmt_0__ campi trovati. + .fields-updated = __ocs_fmt_0__ campi aggiornati. + .invalid-keyword = Parola chiave dell'opzione non valida. + .invalid-boundary = Oggetto di contorno dell'area di conteggio non valido. Selezionare una polilinea chiusa composta da segmenti di linea che non si interseca. + .block-not-found = Impossibile trovare il blocco "__ocs_fmt_0__". + .invalid-point = Punto non valido. diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index 8b1b1dbde..77c7b54d9 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -5916,8 +5916,6 @@ style-manager = .block-extents = ブロック範囲 .base-point = 基点 count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5940,3 +5938,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = __ocs_fmt_0__ 個を検出 + .found-total = __ocs_fmt_0__ 個を検出、合計 __ocs_fmt_1__ 個 + .field-only-in-count = ** COUNTFIELD コマンドはカウント中のみ使用できます。 ** + .area-active = カウント領域が有効です。 + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (読み取り専用) + .requires-0-or-1 = 0 または 1 のみ指定できます。 + .requires-int-range = __ocs_fmt_0__ から __ocs_fmt_1__ までの整数を指定してください。 + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT 現在の文字スタイル: "__ocs_fmt_0__" 文字の高さ: __ocs_fmt_1__ + .fields-found = __ocs_fmt_0__ 個のフィールドが見つかりました。 + .fields-updated = __ocs_fmt_0__ 個のフィールドを更新しました。 + .invalid-keyword = オプションのキーワードが無効です。 + .invalid-boundary = カウント領域の境界オブジェクトが無効です。線分で構成され、自己交差しない閉じたポリラインを選択してください。 + .block-not-found = ブロック "__ocs_fmt_0__" が見つかりません。 + .invalid-point = 点が無効です。 diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index 6c3081482..1d4e4ef29 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -5927,8 +5927,6 @@ style-manager = .block-extents = 블록 범위 .base-point = 기준점 count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5951,3 +5949,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = __ocs_fmt_0__개 찾음 + .found-total = __ocs_fmt_0__개 찾음, 총 __ocs_fmt_1__개 + .field-only-in-count = ** COUNTFIELD 명령은 개수 세기 중에만 사용할 수 있습니다. ** + .area-active = 개수 영역이 활성화되었습니다. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (읽기 전용) + .requires-0-or-1 = 0 또는 1만 입력할 수 있습니다. + .requires-int-range = __ocs_fmt_0__에서 __ocs_fmt_1__ 사이의 정수가 필요합니다. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT 현재 문자 스타일: "__ocs_fmt_0__" 문자 높이: __ocs_fmt_1__ + .fields-found = 필드 __ocs_fmt_0__개를 찾았습니다. + .fields-updated = 필드 __ocs_fmt_0__개를 업데이트했습니다. + .invalid-keyword = 옵션 키워드가 잘못되었습니다. + .invalid-boundary = 개수 영역 경계 객체가 잘못되었습니다. 선분으로 구성되고 자체 교차하지 않는 닫힌 폴리선을 선택하십시오. + .block-not-found = 블록 "__ocs_fmt_0__"을(를) 찾을 수 없습니다. + .invalid-point = 점이 잘못되었습니다. diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index c3fb6b01e..8a7b29a64 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -5926,8 +5926,6 @@ style-manager = .block-extents = Symboolgrenzen .base-point = Basispunt count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5950,3 +5948,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = __ocs_fmt_0__ gevonden + .found-total = __ocs_fmt_0__ gevonden, __ocs_fmt_1__ totaal + .field-only-in-count = ** De opdracht COUNTFIELD is alleen beschikbaar tijdens het tellen. ** + .area-active = Telgebied is actief. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (alleen-lezen) + .requires-0-or-1 = Alleen 0 of 1 toegestaan. + .requires-int-range = Vereist een geheel getal tussen __ocs_fmt_0__ en __ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Huidige tekststijl: "__ocs_fmt_0__" Teksthoogte: __ocs_fmt_1__ + .fields-found = __ocs_fmt_0__ veld(en) gevonden. + .fields-updated = __ocs_fmt_0__ veld(en) bijgewerkt. + .invalid-keyword = Ongeldig optiesleutelwoord. + .invalid-boundary = Ongeldig grensobject voor het telgebied. Selecteer een gesloten polylijn die uit lijnsegmenten bestaat en zichzelf niet snijdt. + .block-not-found = Blok "__ocs_fmt_0__" kan niet worden gevonden. + .invalid-point = Ongeldig punt. diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index 53ad2866a..b425dee41 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -5927,8 +5927,6 @@ style-manager = .block-extents = Zasięg bloku .base-point = Punkt bazowy count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5951,3 +5949,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = Znaleziono: __ocs_fmt_0__ + .found-total = Znaleziono: __ocs_fmt_0__, łącznie: __ocs_fmt_1__ + .field-only-in-count = ** Polecenie COUNTFIELD jest dostępne tylko podczas liczenia. ** + .area-active = Obszar liczenia jest aktywny. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (tylko do odczytu) + .requires-0-or-1 = Wymaga wyłącznie 0 lub 1. + .requires-int-range = Wymaga liczby całkowitej z zakresu od __ocs_fmt_0__ do __ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Bieżący styl tekstu: "__ocs_fmt_0__" Wysokość tekstu: __ocs_fmt_1__ + .fields-found = Znaleziono pól: __ocs_fmt_0__. + .fields-updated = Zaktualizowano pól: __ocs_fmt_0__. + .invalid-keyword = Nieprawidłowe słowo kluczowe opcji. + .invalid-boundary = Nieprawidłowy obiekt obwiedni obszaru liczenia. Wybierz zamkniętą polilinię złożoną z odcinków, która nie przecina samej siebie. + .block-not-found = Nie można znaleźć bloku "__ocs_fmt_0__". + .invalid-point = Nieprawidłowy punkt. diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index 6bfa83486..4f1c800b8 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -5928,8 +5928,6 @@ style-manager = .block-extents = Extensões do bloco .base-point = Ponto base count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5952,3 +5950,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = __ocs_fmt_0__ encontrado(s) + .found-total = __ocs_fmt_0__ encontrado(s), __ocs_fmt_1__ no total + .field-only-in-count = ** O comando COUNTFIELD só está disponível durante a contagem. ** + .area-active = A área de contagem está ativa. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (somente leitura) + .requires-0-or-1 = Requer apenas 0 ou 1. + .requires-int-range = Requer um número inteiro entre __ocs_fmt_0__ e __ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Estilo de texto atual: "__ocs_fmt_0__" Altura do texto: __ocs_fmt_1__ + .fields-found = __ocs_fmt_0__ campo(s) encontrado(s). + .fields-updated = __ocs_fmt_0__ campo(s) atualizado(s). + .invalid-keyword = Palavra-chave de opção inválida. + .invalid-boundary = Objeto de contorno da área de contagem inválido. Selecione uma polilinha fechada composta de segmentos de linha e que não se cruze. + .block-not-found = O bloco "__ocs_fmt_0__" não foi encontrado. + .invalid-point = Ponto inválido. diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index 6bffa6354..3c8c71a8e 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -5929,8 +5929,6 @@ style-manager = .block-extents = Габариты блока .base-point = Базовая точка count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5953,3 +5951,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = Найдено: __ocs_fmt_0__ + .found-total = Найдено: __ocs_fmt_0__, всего: __ocs_fmt_1__ + .field-only-in-count = ** Команда COUNTFIELD доступна только в режиме подсчёта. ** + .area-active = Область подсчёта активна. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (только чтение) + .requires-0-or-1 = Допускается только 0 или 1. + .requires-int-range = Требуется целое число от __ocs_fmt_0__ до __ocs_fmt_1__. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Текущий текстовый стиль: "__ocs_fmt_0__" Высота текста: __ocs_fmt_1__ + .fields-found = Найдено полей: __ocs_fmt_0__. + .fields-updated = Обновлено полей: __ocs_fmt_0__. + .invalid-keyword = Недопустимое ключевое слово параметра. + .invalid-boundary = Недопустимый объект границы области подсчёта. Выберите замкнутую полилинию из отрезков, которая не пересекает саму себя. + .block-not-found = Блок "__ocs_fmt_0__" не найден. + .invalid-point = Недопустимая точка. diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index 945dc938e..43908e04f 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -5851,8 +5851,6 @@ style-manager = .block-extents = Blok sınırları .base-point = Taban noktası count-feature = - .palette = Sayım - .menu = Say .selection = Seçimi say .review = Sayım ayrıntılarını incele .insert-field = Sayım alanı ekle @@ -5875,3 +5873,18 @@ count-feature = .invalid-continue = Devam et ve tüm model alanını say .invalid-continue-detail = Sayım alanı kalkar; sayım tüm model alanında sürer. .invalid-always = Geçerli seçimimi her zaman uygula + .found = __ocs_fmt_0__ bulundu + .found-total = __ocs_fmt_0__ bulundu, toplam __ocs_fmt_1__ + .field-only-in-count = ** COUNTFIELD komutu yalnızca sayım sırasında kullanılabilir. ** + .area-active = Sayım alanı etkin. + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__ (salt okunur) + .requires-0-or-1 = Yalnızca 0 veya 1 girilebilir. + .requires-int-range = __ocs_fmt_0__ ile __ocs_fmt_1__ arasında bir tamsayı gerekir. + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT Geçerli metin stili: "__ocs_fmt_0__" Metin yüksekliği: __ocs_fmt_1__ + .fields-found = __ocs_fmt_0__ alan bulundu. + .fields-updated = __ocs_fmt_0__ alan güncellendi. + .invalid-keyword = Geçersiz seçenek anahtar sözcüğü. + .invalid-boundary = Geçersiz sayım alanı sınır nesnesi. Doğru parçalarından oluşan, kendisiyle kesişmeyen kapalı bir çoklu çizgi seçin. + .block-not-found = "__ocs_fmt_0__" bloğu bulunamadı. + .invalid-point = Geçersiz nokta. diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index a9fdfa9bc..0249f7cfa 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -5911,8 +5911,6 @@ style-manager = .block-extents = 块范围 .base-point = 基点 count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5935,3 +5933,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = 找到 __ocs_fmt_0__ 个 + .found-total = 找到 __ocs_fmt_0__ 个,总计 __ocs_fmt_1__ 个 + .field-only-in-count = ** COUNTFIELD 命令仅在计数期间可用。 ** + .area-active = 计数区域已激活。 + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__(只读) + .requires-0-or-1 = 只能为 0 或 1。 + .requires-int-range = 需要介于 __ocs_fmt_0__ 和 __ocs_fmt_1__ 之间的整数。 + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT 当前文字样式: "__ocs_fmt_0__" 文字高度: __ocs_fmt_1__ + .fields-found = 找到 __ocs_fmt_0__ 个字段。 + .fields-updated = 已更新 __ocs_fmt_0__ 个字段。 + .invalid-keyword = 无效的选项关键字。 + .invalid-boundary = 无效的计数区域边界对象。请选择由直线段组成且不自交的闭合多段线。 + .block-not-found = 找不到块 "__ocs_fmt_0__"。 + .invalid-point = 无效的点。 diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index ec8dffc8b..354f9442d 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -5923,8 +5923,6 @@ style-manager = .block-extents = 圖塊範圍 .base-point = 基點 count-feature = - .palette = Count - .menu = Count .selection = Count Selection .review = Review Count Details .insert-field = Insert Count Field @@ -5947,3 +5945,18 @@ count-feature = .invalid-continue = Continue and count the entire model space .invalid-continue-detail = The count area is dropped; counting goes on in all of model space. .invalid-always = Always perform my current choice + .found = 找到 __ocs_fmt_0__ 個 + .found-total = 找到 __ocs_fmt_0__ 個,總計 __ocs_fmt_1__ 個 + .field-only-in-count = ** COUNTFIELD 指令僅在計數期間可用。 ** + .area-active = 計數區域已啟用。 + .read-only-value = __ocs_fmt_0__ = __ocs_fmt_1__(唯讀) + .requires-0-or-1 = 只能為 0 或 1。 + .requires-int-range = 需要介於 __ocs_fmt_0__ 與 __ocs_fmt_1__ 之間的整數。 + .target-count = __ocs_fmt_0__ ...... __ocs_fmt_1__ + .mtext-current-style = MTEXT 目前文字型式: "__ocs_fmt_0__" 文字高度: __ocs_fmt_1__ + .fields-found = 找到 __ocs_fmt_0__ 個欄位。 + .fields-updated = 已更新 __ocs_fmt_0__ 個欄位。 + .invalid-keyword = 無效的選項關鍵字。 + .invalid-boundary = 無效的計數區域邊界物件。請選取由線段組成且不自我相交的封閉聚合線。 + .block-not-found = 找不到圖塊 "__ocs_fmt_0__"。 + .invalid-point = 無效的點。 diff --git a/src/app/command_driver/viewport.rs b/src/app/command_driver/viewport.rs index 35ceafa46..f8eadd485 100644 --- a/src/app/command_driver/viewport.rs +++ b/src/app/command_driver/viewport.rs @@ -418,7 +418,7 @@ impl OpenCADStudio { } } - pub(super) fn handle_zoom_to_window(&mut self, p1: glam::DVec3, p2: glam::DVec3) { + pub(in crate::app) fn handle_zoom_to_window(&mut self, p1: glam::DVec3, p2: glam::DVec3) { let i = self.active_tab; self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; diff --git a/src/app/commands/count.rs b/src/app/commands/count.rs index d10041a43..06e7f90ea 100644 --- a/src/app/commands/count.rs +++ b/src/app/commands/count.rs @@ -59,7 +59,8 @@ impl OpenCADStudio { let current = matches!(rest.trim_start_matches('_').to_ascii_uppercase().as_str(), "C"); if current && !preselected.is_empty() { // Count Selection: the selection is the target. - self.command_line.push_output(&format!("{} found", preselected.len())); + let found = preselected.len(); + self.command_line.push_output(&crate::tf!("{found} found")); let handles: Vec = preselected.iter().map(|h| hex(*h)).collect(); self.tabs[i].scene.deselect_all(); return Some(self.dispatch_command(&format!("_COUNTRUN C T {}", handles.join(",")))); @@ -67,9 +68,9 @@ impl OpenCADStudio { // Plain COUNT asks for its targets itself. self.tabs[i].scene.deselect_all(); let command = if current { CountCommand::with_area("C") } else { CountCommand::new(false) }; - Some(self.start_count_command(i, Box::new(command), "COUNT")) + Some(self.start_count_command(i, Box::new(command))) } - "COUNTAREA" => Some(self.start_count_command(i, Box::new(CountCommand::new(true)), "COUNTAREA")), + "COUNTAREA" => Some(self.start_count_command(i, Box::new(CountCommand::new(true)))), "COUNTCLOSE" => { self.close_count(i); Some(Task::none()) @@ -91,7 +92,9 @@ impl OpenCADStudio { match self.count_field_code(i) { Some(code) => return Some(self.start_count_field(i, code)), None if self.tabs[i].count.is_some() => {} - None => self.command_line.push_error("** COUNTFIELD command only available during Count. **"), + None => self + .command_line + .push_error(&crate::t!("** COUNTFIELD command only available during Count. **")), } Some(Task::none()) } @@ -115,7 +118,7 @@ impl OpenCADStudio { } } blocks.sort_by_key(|b| b.to_ascii_uppercase()); - Some(self.start_count_command(i, Box::new(CountTableCommand::new(blocks, others)), "COUNTTABLE")) + Some(self.start_count_command(i, Box::new(CountTableCommand::new(blocks, others)))) } "UPDATEFIELD" => { let preselected = self.tabs[i].scene.selected_handles_in_order(); @@ -123,7 +126,7 @@ impl OpenCADStudio { self.update_fields(i, &preselected); return Some(Task::none()); } - Some(self.start_count_command(i, Box::new(UpdateFieldCommand::new()), "UPDATEFIELD")) + Some(self.start_count_command(i, Box::new(UpdateFieldCommand::new()))) } "_UPDATEFIELDRUN" => { let handles: Vec = rest.split(',').filter_map(parse_handle).collect(); @@ -147,7 +150,7 @@ impl OpenCADStudio { mode.cursor = None; self.tabs[i].count = Some(mode); self.apply_count_display(i); - self.command_line.push_output("count area is active."); + self.command_line.push_output(&crate::t!("count area is active.")); } Some(Task::none()) } @@ -164,7 +167,7 @@ impl OpenCADStudio { } } - fn start_count_command(&mut self, i: usize, command: Box, _name: &str) -> Task { + fn start_count_command(&mut self, i: usize, command: Box) -> Task { self.reset_command_start_state(i); self.command_line.push_info(&command.prompt()); self.tabs[i].active_cmd = Some(command); @@ -190,7 +193,7 @@ impl OpenCADStudio { _ => None, }; if let Some(v) = read_only { - self.command_line.push_output(&format!("{name} = {v} (read only)")); + self.command_line.push_output(&crate::tf!("{name} = {v} (read only)")); return; } let (current, min, max) = match name { @@ -199,7 +202,7 @@ impl OpenCADStudio { _ => (self.count_palette.error_color as i32, 1, 255), }; let ask = |app: &mut Self| { - app.command_line.push_output(&format!("Enter new value for {name} <{current}>:")); + app.command_line.push_output(&crate::tf!("Enter new value for {name} <{current}>:")); app.pending_setvar = Some(name.to_string()); }; let Some(value) = value else { @@ -218,9 +221,9 @@ impl OpenCADStudio { } _ => { self.command_line.push_error(&if max == 1 { - "Requires 0 or 1 only.".to_string() + crate::t!("Requires 0 or 1 only.") } else { - format!("Requires an integer between {min} and {max}.") + crate::tf!("Requires an integer between {min} and {max}.") }); ask(self); } @@ -252,8 +255,8 @@ impl OpenCADStudio { let display = self.tabs[i].count.as_ref().filter(|m| m.target.is_some()).map(|m| { let r = m.result(&self.tabs[i].scene.document); crate::scene::CountDisplay { - counted: r.counted.into_iter().collect(), - errors: r.errors.into_iter().chain(r.overlapped).collect(), + counted: r.counted.iter().copied().collect(), + errors: r.errors.iter().chain(&r.overlapped).copied().collect(), color: aci_rgba(self.count_palette.color), error_color: aci_rgba(self.count_palette.error_color), } @@ -303,10 +306,35 @@ impl OpenCADStudio { } /// Invalid Area › Undo (also ✕ and Cancel): the change that took the - /// boundary away is undone. + /// boundary away is reverted — redone when an undo took it, undone + /// otherwise. When that does not bring the boundary back, the history + /// step is put back and the area is dropped as with Continue. fn count_invalid_undo(&mut self, i: usize) { - self.undo_active_tab(); - self.apply_count_display(i); + let Some((boundary, _)) = self.tabs[i].count.as_ref().and_then(|m| m.boundary) else { + return; + }; + // An open step (the edit that just erased the boundary) goes on the + // undo stack first; after that, something to redo means the last + // history step was an undo. + self.finish_pending_history(i); + let redo = !self.tabs[i].history.redo_stack.is_empty(); + if redo || !self.tabs[i].history.undo_stack.is_empty() { + if redo { + self.redo_active_tab(); + } else { + self.undo_active_tab(); + } + if self.tabs[i].scene.document.get_entity(boundary).is_some() { + self.apply_count_display(i); + return; + } + if redo { + self.undo_active_tab(); + } else { + self.redo_active_tab(); + } + } + self.count_invalid_continue(i); } /// Invalid Area › Continue: the area goes, the count covers all of model space. @@ -341,8 +369,10 @@ impl OpenCADStudio { if let Some((h, true)) = boundary { let doc = &self.tabs[i].scene.document; if doc.get_entity(h).is_some() && !boundary_in_use(doc, h) { - self.push_undo_snapshot(i, "COUNT"); - // The area layer is locked; count mode removes its own polyline. + // Count mode removes its own polyline (the area layer is + // locked) outside the history: an open step must not take the + // removal in, or undoing it would bring back an orphan area. + self.finish_pending_history(i); self.tabs[i].scene.rollback_new_entities(&[h]); self.tabs[i].dirty = true; } @@ -465,7 +495,7 @@ impl OpenCADStudio { let mode = CountMode { area, boundary, target, ..CountMode::default() }; if let Some(name) = mode.target_name() { let n = mode.count(&self.tabs[i].scene.document); - self.command_line.push_output(&format!("{name} ...... {n}")); + self.command_line.push_output(&crate::tf!("{name} ...... {n}")); } self.tabs[i].count = Some(mode); self.apply_count_display(i); @@ -503,38 +533,44 @@ impl OpenCADStudio { let doc = &self.tabs[i].scene.document; let value = crate::entities::field::evaluate(doc, &code, &[], None).unwrap_or_else(|| "####".into()); let defaults = crate::scene::creation_style::current_text_defaults(doc); - self.command_line.push_output(&format!( + self.command_line.push_output(&crate::tf!( "MTEXT Current text style: \"{}\" Text height: {:.4}", defaults.style_name, defaults.height )); let command = FieldPlaceCommand::new(value, (code, Vec::new()), defaults.style_name, defaults.height).named("MTEXT"); - self.start_count_command(i, Box::new(command), "COUNTFIELD") + self.start_count_command(i, Box::new(command)) } /// UPDATEFIELD: every field the objects host is evaluated again and its - /// text written back. + /// text written back. A table's fields are hosted by the cell texts of its + /// drawing (its `*T` block); fields a table keeps without such a text are + /// evaluated when drawn and are not counted here. fn update_fields(&mut self, i: usize, handles: &[Handle]) { let doc = &self.tabs[i].scene.document; - let mut updates: Vec<(Handle, String)> = Vec::new(); let mut found = 0; + let mut updates: Vec<(Handle, String)> = Vec::new(); for h in handles { let Some(entity) = doc.get_entity(*h) else { continue }; - if matches!(entity, EntityType::Table(_)) { - // Table cells evaluate their fields when drawn. - if let EntityType::Table(t) = entity { - found += t.field_handles.len(); + let hosts: Vec = match entity { + EntityType::Table(t) => t + .block_record_handle + .and_then(|r| doc.block_records.iter().find(|b| b.handle == r)) + .or_else(|| doc.block_records.get(&t.block_name).filter(|_| !t.block_name.is_empty())) + .map(|record| record.entity_handles.clone()) + .unwrap_or_default(), + _ => vec![*h], + }; + for host in hosts { + if !doc.get_entity(host).is_some_and(|e| crate::entities::field::hosts_field(doc, e)) { + continue; + } + found += 1; + if let Some(text) = crate::entities::field::resolve(doc, host) { + updates.push((host, text)); } - continue; - } - if !crate::entities::field::hosts_field(doc, entity) { - continue; - } - found += 1; - if let Some(text) = crate::entities::field::resolve(doc, *h) { - updates.push((*h, text)); } } - self.command_line.push_output(&format!("{found} field(s) found.")); + self.command_line.push_output(&crate::tf!("{found} field(s) found.")); if found == 0 { return; } @@ -551,15 +587,16 @@ impl OpenCADStudio { changed.push((h, crate::scene::ChangeKind::Modified)); } } - let table_handles: Vec<(Handle, crate::scene::ChangeKind)> = handles - .iter() - .filter(|h| matches!(self.tabs[i].scene.document.get_entity(**h), Some(EntityType::Table(_)))) - .map(|h| (*h, crate::scene::ChangeKind::Modified)) - .collect(); - changed.extend(table_handles); - self.tabs[i].scene.bump_entities(&changed); + let updated = changed.len(); + // Table cell texts live in a block definition. + let scene = &mut self.tabs[i].scene; + if scene.changes_touch_block_definition(&changed) { + scene.bump_geometry(); + } else { + scene.bump_entities(&changed); + } self.tabs[i].dirty = true; - self.command_line.push_output(&format!("{found} field(s) updated.")); + self.command_line.push_output(&crate::tf!("{updated} field(s) updated.")); } /// A count table at `point`: `Item` | `Count`, one row per block (all @@ -652,15 +689,14 @@ impl OpenCADStudio { if outline.is_empty() { return; } - let (mut lo, mut hi) = (glam::Vec3::splat(f32::MAX), glam::Vec3::splat(f32::MIN)); + let (mut lo, mut hi) = (glam::DVec3::splat(f64::MAX), glam::DVec3::splat(f64::MIN)); for c in outline.iter().flat_map(codec::count::Piece::points) { - let p = glam::Vec3::new(c.x as f32, c.y as f32, c.z as f32); + let p = glam::DVec3::new(c.x, c.y, c.z); lo = lo.min(p); hi = hi.max(p); } let pad = (hi - lo) * 1.5; - self.tabs[i].scene.remember_current_view(); - self.tabs[i].scene.zoom_to_window(lo - pad, hi + pad); + self.handle_zoom_to_window(lo - pad, hi + pad); } fn open_count_target(&mut self, i: usize, name: String, key: CountKey) { @@ -773,7 +809,7 @@ impl OpenCADStudio { if names.is_empty() { return Task::none(); } - return self.start_count_command(i, Box::new(CountTableCommand::placing(names)), "COUNTTABLE"); + return self.start_count_command(i, Box::new(CountTableCommand::placing(names))); } CountMsg::Back | CountMsg::Close => self.close_count(i), CountMsg::Match(k, on) => { @@ -787,27 +823,28 @@ impl OpenCADStudio { CountMsg::ShowError(h) => self.zoom_to_insert(i, h), CountMsg::Prev | CountMsg::Next => { let Some(mode) = self.tabs[i].count.as_ref() else { return Task::none() }; - let counted = mode.result(&self.tabs[i].scene.document).counted; - if counted.is_empty() { + let result = mode.result(&self.tabs[i].scene.document); + let n = result.counted.len(); + if n == 0 { return Task::none(); } - let n = counted.len(); let next = match (mode.cursor, matches!(m, CountMsg::Next)) { (None, true) => 0, (None, false) => n - 1, (Some(c), true) => (c + 1) % n, (Some(c), false) => (c + n - 1) % n, }; + let target = result.counted[next]; if let Some(mode) = self.tabs[i].count.as_mut() { mode.cursor = Some(next); } - self.zoom_to_insert(i, counted[next]); + self.zoom_to_insert(i, target); } CountMsg::Area => return self.dispatch_command("COUNTAREA"), CountMsg::Select => { self.tabs[i].scene.deselect_all(); let command = CountCommand::with_area(if self.tabs[i].count.is_some() { "K" } else { "C" }); - return self.start_count_command(i, Box::new(command), "COUNT"); + return self.start_count_command(i, Box::new(command)); } CountMsg::Field => return self.dispatch_command("COUNTFIELD"), CountMsg::InvalidAlways(v) => self.count_palette.invalid_always = v, diff --git a/src/app/control/actions.rs b/src/app/control/actions.rs index 8d63e0176..974939311 100644 --- a/src/app/control/actions.rs +++ b/src/app/control/actions.rs @@ -926,8 +926,6 @@ impl OpenCADStudio { }; Message::PcManager(PcManagerMsg::Toggle(handle, row)) } - // Point Cloud Manager tree: "search=", "collapse", "expand", - // "toggle_node=" or "select=". // Count palette and count mode: "search=", "sort=name|count", // "open=NAME", "child=NAME:" (an expanded row), "menu=:NAME", "create_table", "check=NAME:1", @@ -1000,6 +998,8 @@ impl OpenCADStudio { _ => return Err(bad()), }) } + // Point Cloud Manager tree: "search=", "collapse", "expand", + // "toggle_node=" or "select=". "pc_manager" => { use crate::ui::window::pc_manager::PcManagerMsg as M; let value = string(req, "value")?; diff --git a/src/app/view/mod.rs b/src/app/view/mod.rs index 7a0af5777..021102307 100644 --- a/src/app/view/mod.rs +++ b/src/app/view/mod.rs @@ -3034,6 +3034,7 @@ impl OpenCADStudio { &self.count_palette, tab.count.as_ref(), &tab.scene.document, + tab.id, tab.scene.geometry_epoch, width, auto_collapse, diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index 40758aea5..f657dec83 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -5530,8 +5530,6 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "US Survey Feet" => Some(("common", "us-survey-feet")), "to layout" => Some(("common", "to-layout")), "{count} objects selected" => Some(("common", "count-objects-selected")), - "Count palette" => Some(("count-feature", "palette")), - "Count menu" => Some(("count-feature", "menu")), "Count Selection" => Some(("count-feature", "selection")), "Review Count Details" => Some(("count-feature", "review")), "Insert Count Field" => Some(("count-feature", "insert-field")), @@ -5554,6 +5552,21 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "Continue and count the entire model space" => Some(("count-feature", "invalid-continue")), "The count area is dropped; counting goes on in all of model space." => Some(("count-feature", "invalid-continue-detail")), "Always perform my current choice" => Some(("count-feature", "invalid-always")), + "{found} found" => Some(("count-feature", "found")), + "{found} found, {total} total" => Some(("count-feature", "found-total")), + "** COUNTFIELD command only available during Count. **" => Some(("count-feature", "field-only-in-count")), + "count area is active." => Some(("count-feature", "area-active")), + "{name} = {v} (read only)" => Some(("count-feature", "read-only-value")), + "Requires 0 or 1 only." => Some(("count-feature", "requires-0-or-1")), + "Requires an integer between {min} and {max}." => Some(("count-feature", "requires-int-range")), + "{name} ...... {n}" => Some(("count-feature", "target-count")), + "MTEXT Current text style: \"{}\" Text height: {:.4}" => Some(("count-feature", "mtext-current-style")), + "{found} field(s) found." => Some(("count-feature", "fields-found")), + "{updated} field(s) updated." => Some(("count-feature", "fields-updated")), + "Invalid option keyword." => Some(("count-feature", "invalid-keyword")), + "Invalid count area boundary object. Select a closed polyline consisting of line segments and does not intersect itself." => Some(("count-feature", "invalid-boundary")), + "Block \"{part}\" cannot be found." => Some(("count-feature", "block-not-found")), + "Invalid point." => Some(("count-feature", "invalid-point")), _ => None, } } diff --git a/src/modules/annotate/count_cmd.rs b/src/modules/annotate/count_cmd.rs index f2be96126..9ac6c3d3f 100644 --- a/src/modules/annotate/count_cmd.rs +++ b/src/modules/annotate/count_cmd.rs @@ -9,8 +9,8 @@ // // The command gathers its answers and hands them to the application as // `_COUNTRUN L|T ` (COUNTAREA: `_COUNTAREASET `), the -// area being `C` (current view), `E` (entire model space), `R x,y x,y`, -// `P x,y x,y …` or `O `. +// area being `C` (current area, which counts all of model space), `E` +// (entire model space), `R x,y x,y`, `P x,y x,y …` or `O `. use codec::types::Handle; use codec::EntityType; @@ -82,7 +82,7 @@ impl CountCommand { self.step = Step::PolyStart; CmdResult::NeedPoint } - _ => CmdResult::ReportError("Invalid option keyword.".into()), + _ => CmdResult::ReportError(crate::t!("Invalid option keyword.").into_owned()), } } @@ -150,10 +150,11 @@ impl CadCommand for CountCommand { let found = handles.iter().filter(|h| !self.targets.contains(h)).count(); let first = self.targets.is_empty(); self.targets = handles; + let total = self.targets.len(); CmdResult::ReportMeasurement(if first { - format!("{found} found") + crate::tf!("{found} found").into_owned() } else { - format!("{found} found, {} total", self.targets.len()) + crate::tf!("{found} found, {total} total").into_owned() }) } @@ -175,8 +176,10 @@ impl CadCommand for CountCommand { self.area_done(format!("O {:X}", handle.value())) } _ => CmdResult::CancelWithMessage( - "Invalid count area boundary object. Select a closed polyline consisting of line segments and does not intersect itself." - .into(), + crate::t!( + "Invalid count area boundary object. Select a closed polyline consisting of line segments and does not intersect itself." + ) + .into_owned(), ), } } @@ -298,18 +301,11 @@ impl CountTableCommand { let page: Vec = self.pending.drain(..self.pending.len().min(22)).collect(); if !self.pending.is_empty() { self.step = TableStep::Page; - return CmdResult::ReportMeasurement(page.join(" -")); + return CmdResult::ReportMeasurement(page.join("\n")); } CmdResult::Measurement(format!( - "{} - -User External Dependent Unnamed -Blocks References Blocks Blocks -{:>5}{:>10}{:>12}{:>12} -", - page.join(" -"), + "{}\n\nUser External Dependent Unnamed\nBlocks References Blocks Blocks\n{:>5}{:>10}{:>12}{:>12}\n", + page.join("\n"), self.blocks.len(), self.others[0], self.others[1], @@ -371,7 +367,11 @@ impl CadCommand for CountTableCommand { for part in text.split(',').map(str::trim).filter(|p| !p.is_empty()) { match self.blocks.iter().find(|b| b.eq_ignore_ascii_case(part)) { Some(b) => names.push(b.clone()), - None => return Some(CmdResult::CancelWithMessage(format!("Block \"{part}\" cannot be found."))), + None => { + return Some(CmdResult::CancelWithMessage( + crate::tf!("Block \"{part}\" cannot be found.").into_owned(), + )) + } } } self.names = names; @@ -393,7 +393,7 @@ impl CadCommand for CountTableCommand { fn on_enter(&mut self) -> CmdResult { match self.step { - TableStep::Point => CmdResult::ReportError("Invalid point.".into()), + TableStep::Point => CmdResult::ReportError(crate::t!("Invalid point.").into_owned()), _ => self.on_text_input("").unwrap_or(CmdResult::NeedPoint), } } diff --git a/src/modules/view/count_palette.rs b/src/modules/view/count_palette.rs index fd1d4e652..97321536f 100644 --- a/src/modules/view/count_palette.rs +++ b/src/modules/view/count_palette.rs @@ -4,7 +4,7 @@ pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/d pub fn tool() -> ToolDef { ToolDef { id: "COUNTLIST", - label: "Count palette", + label: "Count", icon: ICON, event: ModuleEvent::Command("_COUNTLISTTOGGLE".to_string()), } diff --git a/src/ui/icons.rs b/src/ui/icons.rs index 7a2385fb4..a2b5af4e7 100644 --- a/src/ui/icons.rs +++ b/src/ui/icons.rs @@ -83,6 +83,8 @@ pub static GEAR: &[u8] = include_bytes!("../../assets/icons/ui/gear.svg"); pub static DOT: &[u8] = include_bytes!("../../assets/icons/ui/dot.svg"); pub static DIRTY_DOT: &[u8] = include_bytes!("../../assets/icons/ui/dirty_dot.svg"); pub static ARROW_LONG_RIGHT: &[u8] = include_bytes!("../../assets/icons/ui/arrow_long_right.svg"); +pub static MORE: &[u8] = include_bytes!("../../assets/icons/ui/more.svg"); +pub static INFO: &[u8] = include_bytes!("../../assets/icons/ui/info.svg"); // ── Status-bar toggle icons (issue #216) ────────────────────────────────── pub static ST_ORTHO: &[u8] = include_bytes!("../../assets/icons/status/ortho.svg"); diff --git a/src/ui/popup/context_menu.rs b/src/ui/popup/context_menu.rs index 407aa66c2..595184c8d 100644 --- a/src/ui/popup/context_menu.rs +++ b/src/ui/popup/context_menu.rs @@ -726,7 +726,7 @@ fn idle_rows( rows.push(MenuRow::Item(if has_selection { cmd(t!("Count Selection").into_owned(), "COUNT _C") } else { - cmd(t!("Count menu").into_owned(), "COUNT") + cmd(t!("Count").into_owned(), "COUNT") })); rows.push(MenuRow::Separator); diff --git a/src/ui/window/count_palette.rs b/src/ui/window/count_palette.rs index 1f31eeb31..8f8e08d70 100644 --- a/src/ui/window/count_palette.rs +++ b/src/ui/window/count_palette.rs @@ -82,10 +82,11 @@ impl CountMode { } } - pub fn result(&self, doc: &CadDocument) -> CountResult { + /// The cached result, or one worked out from the drawing when there is none. + pub fn result(&self, doc: &CadDocument) -> std::borrow::Cow<'_, CountResult> { match &self.cache { - Some((result, _)) => result.clone(), - None => self.compute(doc).0, + Some((result, _)) => std::borrow::Cow::Borrowed(result), + None => std::borrow::Cow::Owned(self.compute(doc).0), } } @@ -158,8 +159,8 @@ pub struct CountPalette { /// What a lost count boundary does without asking: 0 ask, 1 undo, 2 go /// on with all of model space (kept with the user settings). pub invalid_choice: u8, - /// The list's references for (document, geometry epoch, area). - pub list_cache: std::cell::RefCell>, std::rc::Rc>)>>, + /// The list's references for (document tab id, geometry epoch, area). + pub list_cache: std::cell::RefCell>, std::rc::Rc>)>>, } impl Default for CountPalette { @@ -313,7 +314,7 @@ fn list_row<'a>( name: &str, key: CountKey, label: String, - count: String, + count: Option, errors: bool, depth: u16, expanded: Option, @@ -323,7 +324,7 @@ fn list_row<'a>( let n = name.to_string(); checkbox(on).size(14).on_toggle(move |v| msg(CountMsg::TableCheck(n.clone(), v))).into() } else if expanded == Some(true) { - container(text("−").size(13)).width(Length::Fixed(14.0)).into() + container(crate::ui::icons::themed(crate::ui::icons::MINUS, 12.0)).width(Length::Fixed(14.0)).into() } else { Space::new().width(Length::Fixed(14.0)).into() }; @@ -335,7 +336,11 @@ fn list_row<'a>( if errors { cells = cells.push(crate::ui::icons::themed_warning(WARNING_ICON, 12.0)); } - cells = cells.push(text(count).size(12)); + // An expanded row shows its counts on the rows below it. + cells = cells.push(match count { + Some(n) => Element::from(text(n.to_string()).size(12)), + None => crate::ui::icons::themed(crate::ui::icons::MORE, 12.0), + }); let body = container(cells.spacing(6).align_y(iced::Center)).width(Fill).padding([4, 6]); let area = mouse_area(body) .on_press(msg(CountMsg::Open(name.to_string(), key.clone()))) @@ -345,14 +350,11 @@ fn list_row<'a>( } fn header_button<'a>(label: String, active: bool, descending: bool, m: CountMsg) -> Element<'a, Message> { - let arrow = if !active { - "" - } else if descending { - " ▼" - } else { - " ▲" - }; - button(text(format!("{label}{arrow}")).size(11)) + let mut content = row![text(label).size(11)].spacing(3).align_y(iced::Center); + if active { + content = content.push(crate::ui::icons::themed_arrow_toggle(!descending, 8.0)); + } + button(content) .on_press(msg(m)) .style(button::text) .padding([2, 4]) @@ -385,7 +387,7 @@ fn list_view<'a>(palette: &'a CountPalette, instances: &[BlockInstance]) -> Elem let mut list = column![].spacing(1); for r in rows(instances, palette) { let expansion = palette.expansion(&r.name).filter(|e| e.iter().any(|v| *v)); - let count = if expansion.is_some() { "•••".to_string() } else { r.count.to_string() }; + let count = expansion.is_none().then_some(r.count); list = list.push(list_row( palette, &r.name, @@ -399,7 +401,7 @@ fn list_view<'a>(palette: &'a CountPalette, instances: &[BlockInstance]) -> Elem if let Some([l, s, m]) = expansion { for (key, n) in codec::count::expanded_counts(instances, &r.name, l, s, m) { let label = key.label(); - list = list.push(list_row(palette, &r.name, key, label, n.to_string(), false, 1, None)); + list = list.push(list_row(palette, &r.name, key, label, Some(n), false, 1, None)); } } } @@ -525,16 +527,17 @@ pub fn view<'a>( palette: &'a CountPalette, mode: Option<&'a CountMode>, doc: &'a CadDocument, + doc_id: u64, epoch: u64, width: f32, auto_collapse: bool, ) -> Element<'a, Message> { - let title_bar = crate::ui::dock::title_bar(PanelId::Count, crate::t!("Count palette").into_owned(), auto_collapse); + let title_bar = crate::ui::dock::title_bar(PanelId::Count, crate::t!("Count").into_owned(), auto_collapse); let body = match mode { Some(mode) if mode.target.is_some() => mode_view(palette, mode, doc), _ => { let area = mode.and_then(|m| m.area.clone()); - let key = (doc as *const CadDocument as usize, epoch); + let key = (doc_id, epoch); let mut cache = palette.list_cache.borrow_mut(); let instances = match cache.as_ref() { Some((d, e, a, list)) if (*d, *e) == key && *a == area => list.clone(), @@ -567,13 +570,7 @@ pub fn toolbar<'a>(mode: &CountMode, doc: &CadDocument) -> Element<'a, Message> let status: Element<'a, Message> = if !result.errors.is_empty() { crate::ui::icons::themed_warning(WARNING_ICON, 14.0) } else if has_target { - container(text("i").size(11).style(|theme: &Theme| text::Style { color: Some(theme.palette().primary.base.color) })) - .padding([0, 4]) - .style(|theme: &Theme| container::Style { - border: Border { color: theme.palette().primary.base.color, width: 1.0, radius: 8.0.into() }, - ..Default::default() - }) - .into() + crate::ui::icons::themed_primary(crate::ui::icons::INFO, 14.0) } else { crate::ui::icons::themed_disabled(WARNING_ICON, 14.0) }; @@ -628,7 +625,7 @@ pub fn invalid_area_view<'a>(palette: &CountPalette, sizing: crate::ui::modal::M let action = |title: String, detail: String, m: CountMsg| -> Element<'a, Message> { button( row![ - text("→").size(16).style(|theme: &Theme| text::Style { color: Some(theme.palette().primary.base.color) }), + crate::ui::icons::themed_primary(crate::ui::icons::ARROW_LONG_RIGHT, 16.0), column![text(title).size(13), text(detail).size(11).style(muted_style)].spacing(2), ] .spacing(10)