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