forked from 1b-agent/opencadstudio-upstream
feat(blocks): implement WBLOCK dialog and unify dialog buttons and radio builders
This commit is contained in:
1 parent
dddf60d79e
commit
1a6279e841
33 files changed
+1308
-45
No files matched your search
@@ -2316,6 +2316,15 @@ common =
|
||||
.specify-on-screen = تحديد على الشاشة
|
||||
.to-layout = مع التخطيط
|
||||
.us-survey-feet = أقدام مسح أمريكية
|
||||
.entire-drawing = الرسم بالكامل
|
||||
.delete-from-drawing = حذف من الرسم
|
||||
.destination = الوجهة
|
||||
.file-name-and-path = اسم الملف والمسار:
|
||||
.insert-units-label = وحدات الإدراج:
|
||||
.wblock-err-no-block-name = يرجى تحديد أو إدخال اسم الكتلة.
|
||||
.wblock-err-block-not-found = الكتلة "__ocs_fmt_0__" غير موجودة في الرسم.
|
||||
.wblock-err-no-path = يرجى تحديد اسم الملف والمسار.
|
||||
.wblock-help-info = يقوم WBLOCK بكتابة كائنات أو كتلة أو الرسم بالكامل إلى ملف رسم جديد.
|
||||
errors =
|
||||
.save-warning = تحذير الحفظ
|
||||
.unable-to-save-drawing = تعذر حفظ الرسم
|
||||
@@ -3824,6 +3833,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK حدد الكائنات:
|
||||
.block-specify-insertion-base-point = BLOCK حدد نقطة قاعدة الإدراج:
|
||||
.wblock-specify-insertion-base-point = WBLOCK حدد نقطة أساس الإدراج:
|
||||
model =
|
||||
.create = إنشاء
|
||||
.boolean = عمليات منطقية
|
||||
|
||||
@@ -2303,6 +2303,15 @@ common =
|
||||
.specify-on-screen = Указване на екрана
|
||||
.to-layout = с оформлението
|
||||
.us-survey-feet = Геодезически фута (САЩ)
|
||||
.entire-drawing = Цял чертеж
|
||||
.delete-from-drawing = Изтриване от чертежа
|
||||
.destination = Местоназначение
|
||||
.file-name-and-path = Име и път на файла:
|
||||
.insert-units-label = Мерни единици за вмъкване:
|
||||
.wblock-err-no-block-name = Моля, изберете или въведете име на блок.
|
||||
.wblock-err-block-not-found = Блокът "__ocs_fmt_0__" не съществува в чертежа.
|
||||
.wblock-err-no-path = Моля, задайте име и път на файла.
|
||||
.wblock-help-info = WBLOCK записва обекти, блок или целия чертеж в нов чертожен файл.
|
||||
errors =
|
||||
.save-warning = Предупреждение при запазване
|
||||
.unable-to-save-drawing = Чертежът не може да бъде запазен
|
||||
@@ -3811,6 +3820,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Изберете обекти:
|
||||
.block-specify-insertion-base-point = BLOCK Укажете базова точка на вмъкване:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Задайте базова точка на вмъкване:
|
||||
model =
|
||||
.create = Създаване
|
||||
.boolean = Булеви операции
|
||||
|
||||
@@ -2303,6 +2303,15 @@ common =
|
||||
.specify-on-screen = Zadat na obrazovce
|
||||
.to-layout = rozvržení
|
||||
.us-survey-feet = Zeměměřické stopy (USA)
|
||||
.entire-drawing = Celý výkres
|
||||
.delete-from-drawing = Vymazat z výkresu
|
||||
.destination = Cíl
|
||||
.file-name-and-path = Název souboru a cesta:
|
||||
.insert-units-label = Jednotky vložení:
|
||||
.wblock-err-no-block-name = Vyberte nebo zadejte název bloku.
|
||||
.wblock-err-block-not-found = Blok "__ocs_fmt_0__" ve výkresu neexistuje.
|
||||
.wblock-err-no-path = Zadejte název souboru a cestu.
|
||||
.wblock-help-info = WBLOCK zapíše objekty, blok nebo celý výkres do nového výkresového souboru.
|
||||
errors =
|
||||
.save-warning = Uložit varování
|
||||
.unable-to-save-drawing = Nákres nelze uložit
|
||||
@@ -3809,6 +3818,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Vyberte objekty:
|
||||
.block-specify-insertion-base-point = BLOCK Zadejte základní bod vložení:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Určete základní bod vložení:
|
||||
model =
|
||||
.create = Vytvořit
|
||||
.boolean = Booleovské operace
|
||||
|
||||
@@ -2304,6 +2304,15 @@ common =
|
||||
.specify-on-screen = Am Bildschirm bestimmen
|
||||
.to-layout = an Layout
|
||||
.us-survey-feet = US-Vermessungsfuß
|
||||
.entire-drawing = Gesamte Zeichnung
|
||||
.delete-from-drawing = Aus Zeichnung löschen
|
||||
.destination = Ziel
|
||||
.file-name-and-path = Dateiname und Pfad:
|
||||
.insert-units-label = Einfüge-Einheiten:
|
||||
.wblock-err-no-block-name = Bitte wählen Sie einen Blocknamen aus oder geben Sie ihn ein.
|
||||
.wblock-err-block-not-found = Block "__ocs_fmt_0__" ist in der Zeichnung nicht vorhanden.
|
||||
.wblock-err-no-path = Bitte geben Sie einen Dateinamen und Pfad an.
|
||||
.wblock-help-info = WBLOCK schreibt Objekte, einen Block oder die gesamte Zeichnung in eine neue Zeichnungsdatei.
|
||||
errors =
|
||||
.save-warning = Warnhinweise speichern
|
||||
.unable-to-save-drawing = Zeichnung konnte nicht gespeichert werden
|
||||
@@ -3810,6 +3819,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Objekte auswählen:
|
||||
.block-specify-insertion-base-point = BLOCK Einfügebasispunkt angeben:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Basispunkt für Einfügung angeben:
|
||||
model =
|
||||
.create = Erstellen
|
||||
.boolean = Boolesche Operationen
|
||||
|
||||
@@ -2303,6 +2303,15 @@ common =
|
||||
.specify-on-screen = Καθορισμός στην οθόνη
|
||||
.to-layout = με τη διάταξη
|
||||
.us-survey-feet = Τοπογραφικά πόδια ΗΠΑ
|
||||
.entire-drawing = Ολόκληρο σχέδιο
|
||||
.delete-from-drawing = Διαγραφή από το σχέδιο
|
||||
.destination = Προορισμός
|
||||
.file-name-and-path = Όνομα και διαδρομή αρχείου:
|
||||
.insert-units-label = Μονάδες εισαγωγής:
|
||||
.wblock-err-no-block-name = Επιλέξτε ή πληκτρολογήστε ένα όνομα μπλοκ.
|
||||
.wblock-err-block-not-found = Το μπλοκ "__ocs_fmt_0__" δεν υπάρχει στο σχέδιο.
|
||||
.wblock-err-no-path = Καθορίστε ένα όνομα και διαδρομή αρχείου.
|
||||
.wblock-help-info = Η εντολή WBLOCK εγγράφει αντικείμενα, ένα μπλοκ ή ολόκληρο το σχέδιο σε ένα νέο αρχείο σχεδίου.
|
||||
errors =
|
||||
.save-warning = Προειδοποίηση αποθήκευσης
|
||||
.unable-to-save-drawing = Αδυναμία αποθήκευσης σχεδίου
|
||||
@@ -3812,6 +3821,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Επιλέξτε αντικείμενα:
|
||||
.block-specify-insertion-base-point = BLOCK Καθορίστε σημείο βάσης εισαγωγής:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Καθορίστε σημείο βάσης εισαγωγής:
|
||||
model =
|
||||
.create = Δημιουργία
|
||||
.boolean = Δυαδική πράξη
|
||||
|
||||
@@ -2304,6 +2304,16 @@ common =
|
||||
.specify-on-screen = Specify On-screen
|
||||
.to-layout = to layout
|
||||
.us-survey-feet = US Survey Feet
|
||||
.entire-drawing = Entire drawing
|
||||
.delete-from-drawing = Delete from drawing
|
||||
.destination = Destination
|
||||
.file-name-and-path = File name and path:
|
||||
.insert-units-label = Insert units:
|
||||
.wblock-err-no-block-name = Please select or enter a block name.
|
||||
.wblock-err-block-not-found = Block "__ocs_fmt_0__" does not exist in drawing.
|
||||
.wblock-err-no-path = Please specify a file name and path.
|
||||
.wblock-err-current-drawing = Cannot write to the current drawing file.
|
||||
.wblock-help-info = WBLOCK writes objects, a block, or the entire drawing to a new drawing file.
|
||||
errors =
|
||||
.save-warning = Save Warning
|
||||
.unable-to-save-drawing = Unable to Save Drawing
|
||||
@@ -3813,6 +3823,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Select objects:
|
||||
.block-specify-insertion-base-point = BLOCK Specify insertion base point:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Specify insertion base point:
|
||||
model =
|
||||
.create = Create
|
||||
.boolean = Boolean
|
||||
|
||||
@@ -2304,6 +2304,15 @@ common =
|
||||
.specify-on-screen = Precisar en pantalla
|
||||
.to-layout = a la presentación
|
||||
.us-survey-feet = Pies de agrimensura de EE. UU.
|
||||
.entire-drawing = Dibujo completo
|
||||
.delete-from-drawing = Suprimir del dibujo
|
||||
.destination = Destino
|
||||
.file-name-and-path = Nombre de archivo y ruta:
|
||||
.insert-units-label = Unidades de inserción:
|
||||
.wblock-err-no-block-name = Seleccione o escriba un nombre de bloque.
|
||||
.wblock-err-block-not-found = El bloque "__ocs_fmt_0__" no existe en el dibujo.
|
||||
.wblock-err-no-path = Especifique un nombre de archivo y una ruta.
|
||||
.wblock-help-info = WBLOCK escribe objetos, un bloque o el dibujo completo en un nuevo archivo de dibujo.
|
||||
errors =
|
||||
.save-warning = Advertencia de guardado
|
||||
.unable-to-save-drawing = No se puede guardar el dibujo
|
||||
@@ -3812,6 +3821,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Designar objetos:
|
||||
.block-specify-insertion-base-point = BLOCK Precise punto base de inserción:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Precise punto base de inserción:
|
||||
model =
|
||||
.create = Crear
|
||||
.boolean = Booleanas
|
||||
|
||||
@@ -2303,6 +2303,15 @@ common =
|
||||
.specify-on-screen = Määritä näytöltä
|
||||
.to-layout = asetteluun
|
||||
.us-survey-feet = US Survey -jalat
|
||||
.entire-drawing = Koko piirustus
|
||||
.delete-from-drawing = Poista piirustuksesta
|
||||
.destination = Kohde
|
||||
.file-name-and-path = Tiedoston nimi ja polku:
|
||||
.insert-units-label = Lisäysyksiköt:
|
||||
.wblock-err-no-block-name = Valitse tai anna lohkon nimi.
|
||||
.wblock-err-block-not-found = Lohkoa "__ocs_fmt_0__" ei ole piirustuksessa.
|
||||
.wblock-err-no-path = Määritä tiedoston nimi ja polku.
|
||||
.wblock-help-info = WBLOCK kirjoittaa kohteet, lohkon tai koko piirustuksen uuteen piirustustiedostoon.
|
||||
errors =
|
||||
.save-warning = Tallenna varoitus
|
||||
.unable-to-save-drawing = Piirustusta ei voi tallentaa
|
||||
@@ -3811,6 +3820,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Valitse kohteet:
|
||||
.block-specify-insertion-base-point = BLOCK Määritä sijoituksen peruspiste:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Määritä lisäyksen peruspiste:
|
||||
model =
|
||||
.create = Luo
|
||||
.boolean = Boolen operaatiot
|
||||
|
||||
@@ -2304,6 +2304,15 @@ common =
|
||||
.specify-on-screen = Spécifier à l'écran
|
||||
.to-layout = sur la présentation
|
||||
.us-survey-feet = Pieds d'arpentage US
|
||||
.entire-drawing = Dessin entier
|
||||
.delete-from-drawing = Supprimer du dessin
|
||||
.destination = Destination
|
||||
.file-name-and-path = Nom de fichier et chemin d'accès :
|
||||
.insert-units-label = Unités d'insertion :
|
||||
.wblock-err-no-block-name = Veuillez sélectionner ou entrer un nom de bloc.
|
||||
.wblock-err-block-not-found = Le bloc « __ocs_fmt_0__ » n'existe pas dans le dessin.
|
||||
.wblock-err-no-path = Veuillez spécifier un nom de fichier et un chemin d'accès.
|
||||
.wblock-help-info = WBLOCK écrit des objets, un bloc ou l'ensemble du dessin dans un nouveau fichier de dessin.
|
||||
errors =
|
||||
.save-warning = Enregistrer l' avertissement
|
||||
.unable-to-save-drawing = Impossible de sauvegarder le dessin
|
||||
@@ -3812,6 +3821,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Sélectionnez les objets :
|
||||
.block-specify-insertion-base-point = BLOCK Spécifiez le point de base d'insertion :
|
||||
.wblock-specify-insertion-base-point = WBLOCK Spécifiez le point de base d'insertion :
|
||||
model =
|
||||
.create = Créer
|
||||
.boolean = Opérations booléennes
|
||||
|
||||
@@ -2292,6 +2292,15 @@ common =
|
||||
.specify-on-screen = स्क्रीन पर निर्दिष्ट करें
|
||||
.to-layout = लेआउट के अनुसार
|
||||
.us-survey-feet = यूएस सर्वेक्षण फीट
|
||||
.entire-drawing = संपूर्ण रेखाचित्र
|
||||
.delete-from-drawing = रेखाचित्र से हटाएं
|
||||
.destination = गंतव्य
|
||||
.file-name-and-path = फ़ाइल का नाम और पथ:
|
||||
.insert-units-label = सम्मिलन इकाइयाँ:
|
||||
.wblock-err-no-block-name = कृपया एक ब्लॉक नाम चुनें या दर्ज करें।
|
||||
.wblock-err-block-not-found = ब्लॉक "__ocs_fmt_0__" रेखाचित्र में मौजूद नहीं है।
|
||||
.wblock-err-no-path = कृपया फ़ाइल का नाम और पथ निर्दिष्ट करें।
|
||||
.wblock-help-info = WBLOCK ऑब्जेक्ट, एक ब्लॉक, या संपूर्ण रेखाचित्र को एक नई रेखाचित्र फ़ाइल में लिखता है।
|
||||
errors =
|
||||
.save-warning = चेतावनी सहेजें
|
||||
.unable-to-save-drawing = ड्रॉइंग सहेजी नहीं जा सकी
|
||||
@@ -3800,6 +3809,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK ऑब्जेक्ट चुनें:
|
||||
.block-specify-insertion-base-point = BLOCK सम्मिलन आधार बिंदु निर्दिष्ट करें:
|
||||
.wblock-specify-insertion-base-point = WBLOCK सम्मिलन आधार बिंदु निर्दिष्ट करें:
|
||||
model =
|
||||
.create = बनाएँ
|
||||
.boolean = बूलियन संक्रियाएँ
|
||||
|
||||
@@ -2303,6 +2303,15 @@ common =
|
||||
.specify-on-screen = Megadás a képernyőn
|
||||
.to-layout = az elrendezéshez
|
||||
.us-survey-feet = USA geodéziai láb
|
||||
.entire-drawing = Teljes rajz
|
||||
.delete-from-drawing = Törlés a rajzból
|
||||
.destination = Cél
|
||||
.file-name-and-path = Fájlnév és elérési út:
|
||||
.insert-units-label = Beillesztési mértékegységek:
|
||||
.wblock-err-no-block-name = Válasszon vagy adjon meg egy blokknevet.
|
||||
.wblock-err-block-not-found = A(z) "__ocs_fmt_0__" blokk nem létezik a rajzban.
|
||||
.wblock-err-no-path = Adja meg a fájlnevet és az elérési utat.
|
||||
.wblock-help-info = A WBLOCK objektumokat, egy blokkot vagy a teljes rajzot új rajzfájlba menti.
|
||||
errors =
|
||||
.save-warning = Figyelmeztetés mentése
|
||||
.unable-to-save-drawing = Nem sikerült menteni a rajzot
|
||||
@@ -3811,6 +3820,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Válasszon objektumokat:
|
||||
.block-specify-insertion-base-point = BLOCK Adja meg a beillesztési bázispontot:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Adja meg a beillesztési bázispontot:
|
||||
model =
|
||||
.create = Létrehozás
|
||||
.boolean = Logikai műveletek
|
||||
|
||||
@@ -2303,6 +2303,15 @@ common =
|
||||
.specify-on-screen = Specifica sullo schermo
|
||||
.to-layout = al layout
|
||||
.us-survey-feet = Piedi topografici USA
|
||||
.entire-drawing = Intero disegno
|
||||
.delete-from-drawing = Elimina dal disegno
|
||||
.destination = Destinazione
|
||||
.file-name-and-path = Nome file e percorso:
|
||||
.insert-units-label = Unità di inserimento:
|
||||
.wblock-err-no-block-name = Selezionare o immettere il nome di un blocco.
|
||||
.wblock-err-block-not-found = Il blocco "__ocs_fmt_0__" non esiste nel disegno.
|
||||
.wblock-err-no-path = Specificare un nome file e un percorso.
|
||||
.wblock-help-info = WBLOCK scrive gli oggetti, un blocco o l'intero disegno in un nuovo file di disegno.
|
||||
errors =
|
||||
.save-warning = Salva avviso
|
||||
.unable-to-save-drawing = Impossibile salvare il disegno
|
||||
@@ -3811,6 +3820,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Selezionare oggetti:
|
||||
.block-specify-insertion-base-point = BLOCK Specificare punto base di inserimento:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Specificare il punto base di inserimento:
|
||||
model =
|
||||
.create = Crea
|
||||
.boolean = Operazioni booleane
|
||||
|
||||
@@ -2294,6 +2294,15 @@ common =
|
||||
.specify-on-screen = 画面上で指定
|
||||
.to-layout = レイアウトに合わせる
|
||||
.us-survey-feet = 米国測量フィート
|
||||
.entire-drawing = 図面全体
|
||||
.delete-from-drawing = 図面から削除
|
||||
.destination = 保存先
|
||||
.file-name-and-path = ファイル名とパス:
|
||||
.insert-units-label = 挿入単位:
|
||||
.wblock-err-no-block-name = ブロック名を選択または入力してください。
|
||||
.wblock-err-block-not-found = ブロック "__ocs_fmt_0__" は図面に存在しません。
|
||||
.wblock-err-no-path = ファイル名とパスを指定してください。
|
||||
.wblock-help-info = WBLOCK はオブジェクト、ブロック、または図面全体を新しい図面ファイルに書き出します。
|
||||
errors =
|
||||
.save-warning = 保存の警告
|
||||
.unable-to-save-drawing = 図面を保存できません
|
||||
@@ -3800,6 +3809,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK オブジェクトを選択:
|
||||
.block-specify-insertion-base-point = BLOCK 挿入基点を指定:
|
||||
.wblock-specify-insertion-base-point = WBLOCK 挿入基点を指定:
|
||||
model =
|
||||
.create = 作成
|
||||
.boolean = ブール演算
|
||||
|
||||
@@ -2303,6 +2303,15 @@ common =
|
||||
.specify-on-screen = 화면상에 지정
|
||||
.to-layout = 배치에 맞춤
|
||||
.us-survey-feet = 미국 측량 피트
|
||||
.entire-drawing = 도면 전체
|
||||
.delete-from-drawing = 도면에서 삭제
|
||||
.destination = 대상
|
||||
.file-name-and-path = 파일 이름 및 경로:
|
||||
.insert-units-label = 삽입 단위:
|
||||
.wblock-err-no-block-name = 블록 이름을 선택하거나 입력하십시오.
|
||||
.wblock-err-block-not-found = 블록 "__ocs_fmt_0__"이(가) 도면에 존재하지 않습니다.
|
||||
.wblock-err-no-path = 파일 이름과 경로를 지정하십시오.
|
||||
.wblock-help-info = WBLOCK은 객체, 블록 또는 도면 전체를 새 도면 파일로 내보냅니다.
|
||||
errors =
|
||||
.save-warning = 경고 저장
|
||||
.unable-to-save-drawing = 도면을 저장할 수 없습니다
|
||||
@@ -3811,6 +3820,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK 객체 선택:
|
||||
.block-specify-insertion-base-point = BLOCK 삽입 기준점 지정:
|
||||
.wblock-specify-insertion-base-point = WBLOCK 삽입 기준점 지정:
|
||||
model =
|
||||
.create = 생성
|
||||
.boolean = 불리언 연산
|
||||
|
||||
@@ -2304,6 +2304,15 @@ common =
|
||||
.specify-on-screen = Op scherm opgeven
|
||||
.to-layout = aan lay-out
|
||||
.us-survey-feet = US Survey Feet
|
||||
.entire-drawing = Volledige tekening
|
||||
.delete-from-drawing = Verwijderen uit tekening
|
||||
.destination = Bestemming
|
||||
.file-name-and-path = Bestandsnaam en pad:
|
||||
.insert-units-label = Invoegeenheden:
|
||||
.wblock-err-no-block-name = Selecteer of voer een bloknaam in.
|
||||
.wblock-err-block-not-found = Blok "__ocs_fmt_0__" bestaat niet in de tekening.
|
||||
.wblock-err-no-path = Geef een bestandsnaam en pad op.
|
||||
.wblock-help-info = WBLOCK schrijft objecten, een blok of de volledige tekening naar een nieuw tekeningbestand.
|
||||
errors =
|
||||
.save-warning = Waarschuwing opslaan
|
||||
.unable-to-save-drawing = Kan tekening niet opslaan
|
||||
@@ -3810,6 +3819,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Objecten selecteren:
|
||||
.block-specify-insertion-base-point = BLOCK Invoegbasispunt opgeven:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Geef basisinvoegpunt op:
|
||||
model =
|
||||
.create = Maken
|
||||
.boolean = Booleaanse bewerkingen
|
||||
|
||||
@@ -2303,6 +2303,15 @@ common =
|
||||
.specify-on-screen = Określ na ekranie
|
||||
.to-layout = do układu
|
||||
.us-survey-feet = Stopy geodezyjne USA
|
||||
.entire-drawing = Cały rysunek
|
||||
.delete-from-drawing = Usuń z rysunku
|
||||
.destination = Cel
|
||||
.file-name-and-path = Nazwa pliku i ścieżka:
|
||||
.insert-units-label = Jednostki wstawiania:
|
||||
.wblock-err-no-block-name = Wybierz lub wprowadź nazwę bloku.
|
||||
.wblock-err-block-not-found = Blok „__ocs_fmt_0__” nie istnieje w rysunku.
|
||||
.wblock-err-no-path = Podaj nazwę pliku i ścieżkę.
|
||||
.wblock-help-info = WBLOCK zapisuje obiekty, blok lub cały rysunek do nowego pliku rysunku.
|
||||
errors =
|
||||
.save-warning = Zapisz ostrzeżenie
|
||||
.unable-to-save-drawing = Nie można zapisać rysunku
|
||||
@@ -3811,6 +3820,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Wybierz obiekty:
|
||||
.block-specify-insertion-base-point = BLOCK Określ bazowy punkt wstawienia:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Określ punkt bazowy wstawienia:
|
||||
model =
|
||||
.create = Utwórz
|
||||
.boolean = Operacje boolowskie
|
||||
|
||||
@@ -2304,6 +2304,15 @@ common =
|
||||
.specify-on-screen = Especificar na tela
|
||||
.to-layout = ao layout
|
||||
.us-survey-feet = Pés topográficos dos EUA
|
||||
.entire-drawing = Desenho inteiro
|
||||
.delete-from-drawing = Excluir do desenho
|
||||
.destination = Destino
|
||||
.file-name-and-path = Nome do arquivo e caminho:
|
||||
.insert-units-label = Unidades de inserção:
|
||||
.wblock-err-no-block-name = Selecione ou insira o nome de um bloco.
|
||||
.wblock-err-block-not-found = O bloco "__ocs_fmt_0__" não existe no desenho.
|
||||
.wblock-err-no-path = Especifique um nome de arquivo e caminho.
|
||||
.wblock-help-info = O WBLOCK grava objetos, um bloco ou o desenho inteiro em um novo arquivo de desenho.
|
||||
errors =
|
||||
.save-warning = Aviso de salvamento
|
||||
.unable-to-save-drawing = Não foi possível salvar o desenho
|
||||
@@ -3812,6 +3821,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Selecionar objetos:
|
||||
.block-specify-insertion-base-point = BLOCK Especificar ponto base de inserção:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Especifique o ponto base de inserção:
|
||||
model =
|
||||
.create = Criar
|
||||
.boolean = Operações booleanas
|
||||
|
||||
@@ -2307,6 +2307,15 @@ common =
|
||||
.specify-on-screen = Указать на экране
|
||||
.to-layout = с листом
|
||||
.us-survey-feet = Геодезические футы США
|
||||
.entire-drawing = Весь чертеж
|
||||
.delete-from-drawing = Удалить из чертежа
|
||||
.destination = Место назначения
|
||||
.file-name-and-path = Имя файла и путь:
|
||||
.insert-units-label = Единицы вставки:
|
||||
.wblock-err-no-block-name = Выберите или введите имя блока.
|
||||
.wblock-err-block-not-found = Блок "__ocs_fmt_0__" отсутствует в чертеже.
|
||||
.wblock-err-no-path = Укажите имя файла и путь к нему.
|
||||
.wblock-help-info = WBLOCK записывает объекты, блок или весь чертеж в новый файл чертежа.
|
||||
errors =
|
||||
.save-warning = Спасти предостережение
|
||||
.unable-to-save-drawing = Не удалось сохранить чертёж
|
||||
@@ -3813,6 +3822,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Выберите объекты:
|
||||
.block-specify-insertion-base-point = BLOCK Укажите базовую точку вставки:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Укажите базовую точку вставки:
|
||||
model =
|
||||
.create = Создание
|
||||
.boolean = Булевы операции
|
||||
|
||||
@@ -2288,6 +2288,15 @@ common =
|
||||
.specify-on-screen = Ekranda Belirt
|
||||
.to-layout = düzene
|
||||
.us-survey-feet = ABD Ölçüm Fiti
|
||||
.entire-drawing = Tüm çizim
|
||||
.delete-from-drawing = Çizimden sil
|
||||
.destination = Hedef
|
||||
.file-name-and-path = Dosya adı ve yolu:
|
||||
.insert-units-label = Ekleme birimleri:
|
||||
.wblock-err-no-block-name = Lütfen bir blok adı seçin veya girin.
|
||||
.wblock-err-block-not-found = "__ocs_fmt_0__" bloğu çizimde mevcut değil.
|
||||
.wblock-err-no-path = Lütfen bir dosya adı ve yolu belirtin.
|
||||
.wblock-help-info = WBLOCK nesneleri, bir bloğu veya tüm çizimi yeni bir çizim dosyasına yazar.
|
||||
errors =
|
||||
.save-warning = Kaydetme Uyarısı
|
||||
.unable-to-save-drawing = Çizim Kaydedilemiyor
|
||||
@@ -3772,6 +3781,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK Nesneleri seçin:
|
||||
.block-specify-insertion-base-point = BLOCK Ekleme taban noktasını belirtin:
|
||||
.wblock-specify-insertion-base-point = WBLOCK Ekleme taban noktasını belirleyin:
|
||||
model =
|
||||
.create = Oluştur
|
||||
.boolean = Boole işlemleri
|
||||
|
||||
@@ -2291,6 +2291,15 @@ common =
|
||||
.specify-on-screen = 在屏幕上指定
|
||||
.to-layout = 匹配到布局
|
||||
.us-survey-feet = 美国测量英尺
|
||||
.entire-drawing = 整个图形
|
||||
.delete-from-drawing = 从图形中删除
|
||||
.destination = 目标
|
||||
.file-name-and-path = 文件名和路径:
|
||||
.insert-units-label = 插入单位:
|
||||
.wblock-err-no-block-name = 请选择或输入块名称。
|
||||
.wblock-err-block-not-found = 图形中不存在块“__ocs_fmt_0__”。
|
||||
.wblock-err-no-path = 请指定文件名和路径。
|
||||
.wblock-help-info = WBLOCK 将对象、块或整个图形写入新的图形文件。
|
||||
errors =
|
||||
.save-warning = 保存警告
|
||||
.unable-to-save-drawing = 无法保存图形
|
||||
@@ -3795,6 +3804,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK 选择对象:
|
||||
.block-specify-insertion-base-point = BLOCK 指定插入基点:
|
||||
.wblock-specify-insertion-base-point = WBLOCK 指定插入基点:
|
||||
model =
|
||||
.create = 创建
|
||||
.boolean = 布尔运算
|
||||
|
||||
@@ -2303,6 +2303,15 @@ common =
|
||||
.specify-on-screen = 在螢幕上指定
|
||||
.to-layout = 與配置相符
|
||||
.us-survey-feet = 美國測量英呎
|
||||
.entire-drawing = 整個圖面
|
||||
.delete-from-drawing = 從圖面中刪除
|
||||
.destination = 目標
|
||||
.file-name-and-path = 檔名和路徑:
|
||||
.insert-units-label = 插入單位:
|
||||
.wblock-err-no-block-name = 請選取或輸入圖塊名稱。
|
||||
.wblock-err-block-not-found = 圖面中不存在圖塊「__ocs_fmt_0__」。
|
||||
.wblock-err-no-path = 請指定檔名和路徑。
|
||||
.wblock-help-info = WBLOCK 將物件、圖塊或整個圖面寫入新的圖面檔案。
|
||||
errors =
|
||||
.save-warning = 儲存警告
|
||||
.unable-to-save-drawing = 無法儲存圖形
|
||||
@@ -3807,6 +3816,7 @@ insert =
|
||||
.xref = XREF: __ocs_fmt_0__
|
||||
.block-select-objects = BLOCK 選取物件:
|
||||
.block-specify-insertion-base-point = BLOCK 指定插入基準點:
|
||||
.wblock-specify-insertion-base-point = WBLOCK 指定插入基準點:
|
||||
model =
|
||||
.create = 建立
|
||||
.boolean = 布林運算
|
||||
|
||||
@@ -460,6 +460,41 @@ impl OpenCADStudio {
|
||||
self.active_modal = Some(crate::app::ModalKind::BlockDefinition);
|
||||
}
|
||||
|
||||
cmd if cmd.starts_with("WBLOCK_POINT_PICKED ") => {
|
||||
let parts: Vec<f64> = cmd["WBLOCK_POINT_PICKED ".len()..]
|
||||
.split_whitespace()
|
||||
.filter_map(|s| s.parse::<f64>().ok())
|
||||
.collect();
|
||||
if parts.len() == 3 {
|
||||
if let Some(state) = self.wblock.as_mut() {
|
||||
state.base_point_x = format!("{:.4}", parts[0]);
|
||||
state.base_point_y = format!("{:.4}", parts[1]);
|
||||
state.base_point_z = format!("{:.4}", parts[2]);
|
||||
}
|
||||
}
|
||||
self.tabs[i].active_cmd = None;
|
||||
self.active_modal = Some(crate::app::ModalKind::WriteBlock);
|
||||
}
|
||||
|
||||
"WBLOCK_POINT_CANCELLED" => {
|
||||
self.tabs[i].active_cmd = None;
|
||||
self.active_modal = Some(crate::app::ModalKind::WriteBlock);
|
||||
}
|
||||
|
||||
"WBLOCK_OBJECTS_GATHERED" => {
|
||||
let handles: Vec<_> = self.tabs[i]
|
||||
.scene
|
||||
.selected_entities()
|
||||
.into_iter()
|
||||
.map(|(h, _)| h)
|
||||
.collect();
|
||||
if let Some(state) = self.wblock.as_mut() {
|
||||
state.selected_handles = handles;
|
||||
}
|
||||
self.tabs[i].active_cmd = None;
|
||||
self.active_modal = Some(crate::app::ModalKind::WriteBlock);
|
||||
}
|
||||
|
||||
"INSERT" => {
|
||||
let blocks = self.tabs[i].scene.custom_block_names();
|
||||
if blocks.is_empty() {
|
||||
@@ -663,9 +698,60 @@ impl OpenCADStudio {
|
||||
"PDFATTACH" => {
|
||||
return Some(Task::done(Message::PdfAttachPick));
|
||||
}
|
||||
cmd if cmd == "WBLOCK" || cmd == "WB" || cmd.starts_with("WBLOCK ") => {
|
||||
let arg = cmd.splitn(2, ' ').nth(1).unwrap_or("").trim();
|
||||
if arg.is_empty() {
|
||||
"XATTACH" => {
|
||||
// Launch the file picker; XAttachPickResult will start the command.
|
||||
return Some(Task::done(Message::XAttachPick));
|
||||
}
|
||||
"WBLOCK" | "WB" => {
|
||||
let handles: Vec<_> = self.tabs[i]
|
||||
.scene
|
||||
.selected_entities()
|
||||
.into_iter()
|
||||
.map(|(h, _)| h)
|
||||
.collect();
|
||||
let existing_blocks = self.tabs[i].scene.custom_block_names();
|
||||
let default_unit = self.tabs[i].scene.document.header.insertion_units;
|
||||
let default_folder = self.tabs[i]
|
||||
.current_path
|
||||
.as_ref()
|
||||
.and_then(|p| p.parent())
|
||||
.map(|p| p.to_string_lossy().to_string())
|
||||
.unwrap_or_default();
|
||||
let default_path = if default_folder.is_empty() {
|
||||
"new_block.dwg".to_string()
|
||||
} else {
|
||||
format!("{}/new_block.dwg", default_folder.replace('\\', "/"))
|
||||
};
|
||||
self.wblock = Some(
|
||||
crate::ui::window::wblock::WblockState::new(
|
||||
existing_blocks,
|
||||
handles,
|
||||
default_unit,
|
||||
default_path,
|
||||
),
|
||||
);
|
||||
self.active_modal = Some(crate::app::ModalKind::WriteBlock);
|
||||
}
|
||||
|
||||
cmd if cmd == "-WBLOCK"
|
||||
|| cmd == "-WB"
|
||||
|| cmd.starts_with("-WBLOCK ")
|
||||
|| cmd.starts_with("-WB ")
|
||||
|| cmd.starts_with("WBLOCK ")
|
||||
|| cmd.starts_with("WB ") =>
|
||||
{
|
||||
let rest = if let Some(r) = cmd.strip_prefix("-WBLOCK") {
|
||||
r.trim()
|
||||
} else if let Some(r) = cmd.strip_prefix("-WB") {
|
||||
r.trim()
|
||||
} else if let Some(r) = cmd.strip_prefix("WBLOCK") {
|
||||
r.trim()
|
||||
} else if let Some(r) = cmd.strip_prefix("WB") {
|
||||
r.trim()
|
||||
} else {
|
||||
""
|
||||
};
|
||||
if rest.is_empty() {
|
||||
// No argument: use selected entities (*) if any, else ask.
|
||||
let sel: Vec<_> = self.tabs[i].scene.selected.iter().copied().collect();
|
||||
if sel.is_empty() {
|
||||
@@ -676,7 +762,7 @@ impl OpenCADStudio {
|
||||
return Some(Task::done(Message::WblockSave("*".to_string())));
|
||||
}
|
||||
} else {
|
||||
return Some(Task::done(Message::WblockSave(arg.to_string())));
|
||||
return Some(Task::done(Message::WblockSave(rest.to_string())));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -495,6 +495,8 @@ pub(super) struct OpenCADStudio {
|
||||
block_definition: Option<crate::ui::window::block_definition::BlockDefinitionState>,
|
||||
/// Working copy of the Attach External Reference dialog; None while closed.
|
||||
xref_attach: Option<crate::ui::window::xref_attach::XrefAttachState>,
|
||||
/// Working copy of the Write Block (WBLOCK) dialog; `None` while it is closed.
|
||||
wblock: Option<crate::ui::window::wblock::WblockState>,
|
||||
/// Working copy of the structured feature-control-frame editor.
|
||||
geometric_tolerance: Option<crate::ui::window::geometric_tolerance::State>,
|
||||
/// PICKDRAG (#226): false (default) = press-drag lassoes; true =
|
||||
@@ -1883,6 +1885,7 @@ pub enum ModalKind {
|
||||
DrawingUnits,
|
||||
BlockDefinition,
|
||||
XrefAttach,
|
||||
WriteBlock,
|
||||
GeometricTolerance,
|
||||
DraftingSettings,
|
||||
AutoConstrainSettings,
|
||||
@@ -2880,6 +2883,24 @@ pub enum Message {
|
||||
BlockDefConfirmRedefine(bool),
|
||||
BlockDefDismissError,
|
||||
BlockDefHelp,
|
||||
/// Write Block (WBLOCK) dialog messages
|
||||
WblockSourceMode(crate::ui::window::wblock::WblockSourceMode),
|
||||
WblockBlockName(String),
|
||||
WblockBlockSelect(String),
|
||||
WblockPickPoint,
|
||||
WblockBaseX(String),
|
||||
WblockBaseY(String),
|
||||
WblockBaseZ(String),
|
||||
WblockSelectObjects,
|
||||
WblockQuickSelect,
|
||||
WblockObjectMode(crate::ui::window::wblock::WblockObjectMode),
|
||||
WblockFilePath(String),
|
||||
WblockBrowsePath,
|
||||
WblockBrowsePathResult(Option<std::path::PathBuf>),
|
||||
WblockUnit(i16),
|
||||
WblockApply,
|
||||
WblockDismissError,
|
||||
WblockHelp,
|
||||
/// One structured feature-control-frame field changed.
|
||||
ToleranceDialogField(crate::ui::window::geometric_tolerance::Field),
|
||||
/// One structured feature-control-frame option changed.
|
||||
@@ -3962,6 +3983,7 @@ impl OpenCADStudio {
|
||||
drawing_units: None,
|
||||
block_definition: None,
|
||||
xref_attach: None,
|
||||
wblock: None,
|
||||
geometric_tolerance: None,
|
||||
pick_drag_rect: false,
|
||||
perf_hud: false,
|
||||
|
||||
@@ -1163,6 +1163,8 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
|
||||
self.reset_modal_geometry();
|
||||
if self.block_definition.is_some() {
|
||||
self.active_modal = Some(crate::app::ModalKind::BlockDefinition);
|
||||
} else if self.wblock.is_some() {
|
||||
self.active_modal = Some(crate::app::ModalKind::WriteBlock);
|
||||
}
|
||||
return Task::none();
|
||||
}
|
||||
|
||||
@@ -209,6 +209,7 @@ impl OpenCADStudio {
|
||||
Some(GeometricTolerance) => self.geometric_tolerance = None,
|
||||
Some(BlockDefinition) => self.block_definition = None,
|
||||
Some(XrefAttach) => self.xref_attach = None,
|
||||
Some(WriteBlock) => self.wblock = None,
|
||||
Some(Hyperlink) => {
|
||||
self.hyperlink_editor_handles.clear();
|
||||
self.hyperlink_editor_url.clear();
|
||||
@@ -346,6 +347,14 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.active_modal == Some(super::ModalKind::WriteBlock) {
|
||||
if let Some(ref mut state) = self.wblock {
|
||||
if state.error_message.is_some() {
|
||||
state.error_message = None;
|
||||
return Task::none();
|
||||
}
|
||||
}
|
||||
}
|
||||
return self.update(Message::CloseModal);
|
||||
}
|
||||
if self.active_modal == Some(super::ModalKind::BlockDefinition) {
|
||||
@@ -362,6 +371,13 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.active_modal == Some(super::ModalKind::WriteBlock) {
|
||||
if matches!(msg, Message::CommandFinalize)
|
||||
|| matches!(&msg, Message::ShortcutPressed(key) if key.rsplit('+').next() == Some("ENTER") || key.rsplit('+').next() == Some("RETURN"))
|
||||
{
|
||||
return self.update(Message::WblockApply);
|
||||
}
|
||||
}
|
||||
if is_modal_blocked_key_msg(&msg) {
|
||||
return Task::none();
|
||||
}
|
||||
@@ -4950,6 +4966,294 @@ impl OpenCADStudio {
|
||||
}
|
||||
self.commit_block_definition(false)
|
||||
}
|
||||
Message::WblockSourceMode(mode) => {
|
||||
if let Some(state) = self.wblock.as_mut() {
|
||||
state.source_mode = mode;
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockBlockName(name) => {
|
||||
if let Some(state) = self.wblock.as_mut() {
|
||||
state.block_name = name;
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockBlockSelect(name) => {
|
||||
if let Some(state) = self.wblock.as_mut() {
|
||||
state.block_name = name.clone();
|
||||
let trimmed = name.trim();
|
||||
if !trimmed.is_empty() {
|
||||
let current_path = std::path::Path::new(&state.file_path);
|
||||
let file_stem = current_path.file_stem().and_then(|s| s.to_str());
|
||||
let is_default_or_block = file_stem == Some("new_block")
|
||||
|| state.existing_blocks.iter().any(|b| Some(b.as_str()) == file_stem);
|
||||
if is_default_or_block {
|
||||
let new_file_name = format!("{}.dwg", trimmed);
|
||||
if let Some(parent) = current_path.parent() {
|
||||
if !parent.as_os_str().is_empty() {
|
||||
state.file_path = parent.join(new_file_name).to_string_lossy().to_string();
|
||||
} else {
|
||||
state.file_path = new_file_name;
|
||||
}
|
||||
} else {
|
||||
state.file_path = new_file_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockPickPoint => {
|
||||
self.active_modal = None;
|
||||
let cmd = crate::modules::insert::wblock::WblockPickBasePointCommand;
|
||||
self.command_line.push_info(&cmd.prompt());
|
||||
self.tabs[self.active_tab].active_cmd = Some(Box::new(cmd));
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockBaseX(val) => {
|
||||
if let Some(state) = self.wblock.as_mut() {
|
||||
state.base_point_x = val;
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockBaseY(val) => {
|
||||
if let Some(state) = self.wblock.as_mut() {
|
||||
state.base_point_y = val;
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockBaseZ(val) => {
|
||||
if let Some(state) = self.wblock.as_mut() {
|
||||
state.base_point_z = val;
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockSelectObjects => {
|
||||
self.active_modal = None;
|
||||
use crate::modules::draw::select::SelectObjectsCommand;
|
||||
let cmd = SelectObjectsCommand::plain("WBLOCK", "WBLOCK_OBJECTS_GATHERED");
|
||||
self.command_line.push_info(&cmd.prompt());
|
||||
self.tabs[self.active_tab].active_cmd = Some(Box::new(cmd));
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockQuickSelect => {
|
||||
self.active_modal = None;
|
||||
self.on_qselect_open()
|
||||
}
|
||||
Message::WblockObjectMode(mode) => {
|
||||
if let Some(state) = self.wblock.as_mut() {
|
||||
state.object_mode = mode;
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockFilePath(path) => {
|
||||
if let Some(state) = self.wblock.as_mut() {
|
||||
state.file_path = path;
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockBrowsePath => {
|
||||
let default_name = if let Some(state) = self.wblock.as_ref() {
|
||||
let p = std::path::Path::new(&state.file_path);
|
||||
p.file_name()
|
||||
.and_then(|f| f.to_str())
|
||||
.unwrap_or("new_block.dwg")
|
||||
.to_string()
|
||||
} else {
|
||||
"new_block.dwg".to_string()
|
||||
};
|
||||
Task::perform(
|
||||
async move {
|
||||
let path = crate::sys::file_dialog()
|
||||
.set_title(crate::t!("Save Block As").as_ref())
|
||||
.set_file_name(&default_name)
|
||||
.add_filter(crate::t!("DWG Files").as_ref(), &["dwg"])
|
||||
.add_filter(crate::t!("DXF Files").as_ref(), &["dxf"])
|
||||
.save_file()
|
||||
.await
|
||||
.map(|h| crate::sys::handle_path(&h));
|
||||
path
|
||||
},
|
||||
|path| Message::WblockBrowsePathResult(path),
|
||||
)
|
||||
}
|
||||
Message::WblockBrowsePathResult(opt_path) => {
|
||||
if let Some(path) = opt_path {
|
||||
if let Some(state) = self.wblock.as_mut() {
|
||||
state.file_path = path.to_string_lossy().to_string();
|
||||
}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockUnit(unit) => {
|
||||
if let Some(state) = self.wblock.as_mut() {
|
||||
state.unit = unit;
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockDismissError => {
|
||||
if let Some(state) = self.wblock.as_mut() {
|
||||
state.error_message = None;
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockHelp => {
|
||||
self.command_line.push_info(
|
||||
crate::t!("WBLOCK writes objects, a block, or the entire drawing to a new drawing file.").as_ref(),
|
||||
);
|
||||
Task::none()
|
||||
}
|
||||
Message::WblockApply => {
|
||||
let Some(state) = self.wblock.as_mut() else {
|
||||
return Task::none();
|
||||
};
|
||||
use crate::ui::window::wblock::{WblockObjectMode, WblockSourceMode};
|
||||
match state.source_mode {
|
||||
WblockSourceMode::Block => {
|
||||
let name = state.block_name.trim();
|
||||
if name.is_empty() {
|
||||
state.error_message =
|
||||
Some(crate::t!("Please select or enter a block name.").into_owned());
|
||||
return Task::none();
|
||||
}
|
||||
let i = self.active_tab;
|
||||
if self.tabs[i].scene.document.block_records.get(name).is_none() {
|
||||
state.error_message = Some(
|
||||
crate::tf!("Block \"{}\" does not exist in drawing.", name)
|
||||
.into_owned(),
|
||||
);
|
||||
return Task::none();
|
||||
}
|
||||
}
|
||||
WblockSourceMode::Objects => {
|
||||
if state.selected_handles.is_empty() {
|
||||
state.error_message = Some(
|
||||
crate::t!("No objects selected. You must select objects to define a block.")
|
||||
.into_owned(),
|
||||
);
|
||||
return Task::none();
|
||||
}
|
||||
}
|
||||
WblockSourceMode::EntireDrawing => {}
|
||||
}
|
||||
|
||||
let path_str = state.file_path.trim().to_string();
|
||||
if path_str.is_empty() {
|
||||
state.error_message =
|
||||
Some(crate::t!("Please specify a file name and path.").into_owned());
|
||||
return Task::none();
|
||||
}
|
||||
|
||||
let mut path = std::path::PathBuf::from(path_str);
|
||||
if path.extension().is_none() {
|
||||
path.set_extension("dwg");
|
||||
}
|
||||
|
||||
let i = self.active_tab;
|
||||
if let Some(current_path) = self.tabs[i].current_path.as_ref() {
|
||||
if current_path == &path {
|
||||
state.error_message = Some(
|
||||
crate::t!("Cannot write to the current drawing file.").into_owned(),
|
||||
);
|
||||
return Task::none();
|
||||
}
|
||||
}
|
||||
|
||||
let state = self.wblock.take().unwrap();
|
||||
self.active_modal = None;
|
||||
let document = self.tabs[i].scene.document_for_save();
|
||||
let source_mode = state.source_mode;
|
||||
let block_name = state.block_name.trim().to_string();
|
||||
let handles = state.selected_handles.clone();
|
||||
let base_point = state.parse_base_point();
|
||||
let unit = state.unit;
|
||||
let object_mode = state.object_mode;
|
||||
|
||||
if source_mode == WblockSourceMode::Objects {
|
||||
match object_mode {
|
||||
WblockObjectMode::Retain => {}
|
||||
WblockObjectMode::Delete => {
|
||||
self.push_undo_snapshot(i, "WBLOCK");
|
||||
self.tabs[i].scene.erase_entities(&handles);
|
||||
self.tabs[i].dirty = true;
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
self.refresh_properties();
|
||||
}
|
||||
WblockObjectMode::Convert => {
|
||||
let block_name_for_conv = path
|
||||
.file_stem()
|
||||
.and_then(|s| s.to_str())
|
||||
.unwrap_or("WBLOCK")
|
||||
.to_string();
|
||||
self.push_undo_snapshot(i, "WBLOCK");
|
||||
let ucs = self.tabs[i].ucs_xform();
|
||||
let world_to_block = ucs.to_ucs_transform_at(base_point);
|
||||
let block_to_world = ucs.to_wcs_transform_at(base_point);
|
||||
let options = crate::scene::CreateBlockOptions {
|
||||
name: block_name_for_conv,
|
||||
handles: handles.clone(),
|
||||
base_point,
|
||||
world_to_block,
|
||||
block_to_world,
|
||||
mode: crate::ui::window::block_definition::BlockObjectMode::Convert,
|
||||
annotative: false,
|
||||
match_orientation: false,
|
||||
scale_uniformly: false,
|
||||
allow_exploding: true,
|
||||
unit,
|
||||
description: String::new(),
|
||||
hyperlink_url: String::new(),
|
||||
hyperlink_desc: String::new(),
|
||||
redefine: true,
|
||||
};
|
||||
let _ = self.tabs[i].scene.create_block_with_options(options);
|
||||
self.tabs[i].dirty = true;
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
self.refresh_properties();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let worker_path = path.clone();
|
||||
let display_name = match source_mode {
|
||||
WblockSourceMode::Block => block_name.clone(),
|
||||
WblockSourceMode::EntireDrawing => "*".to_string(),
|
||||
WblockSourceMode::Objects => "*".to_string(),
|
||||
};
|
||||
let worker_display = display_name.clone();
|
||||
|
||||
file::background_task(
|
||||
move || {
|
||||
let out_doc = match source_mode {
|
||||
WblockSourceMode::Block => {
|
||||
let mut d = crate::modules::insert::wblock::extract_block_to_doc(
|
||||
&document,
|
||||
&block_name,
|
||||
)
|
||||
.map_err(|e| e.to_string())?;
|
||||
d.header.insertion_units = unit;
|
||||
d
|
||||
}
|
||||
WblockSourceMode::EntireDrawing => {
|
||||
let mut d = document.clone();
|
||||
d.header.insertion_units = unit;
|
||||
d
|
||||
}
|
||||
WblockSourceMode::Objects => {
|
||||
crate::modules::insert::wblock::extract_entities_to_doc_with_base(
|
||||
&document,
|
||||
&handles,
|
||||
base_point,
|
||||
unit,
|
||||
)
|
||||
.map_err(|e| e.to_string())?
|
||||
}
|
||||
};
|
||||
crate::io::save(&out_doc, &worker_path).map_err(|e| e.to_string())
|
||||
},
|
||||
move |result| Message::WblockWriteFinished(worker_display, path, result),
|
||||
)
|
||||
}
|
||||
Message::ToleranceDialogField(field) => {
|
||||
if let Some(state) = self.geometric_tolerance.as_mut() {
|
||||
state.apply_field(field);
|
||||
@@ -5904,6 +6208,8 @@ impl OpenCADStudio {
|
||||
self.reset_modal_geometry();
|
||||
if self.block_definition.is_some() {
|
||||
self.active_modal = Some(super::ModalKind::BlockDefinition);
|
||||
} else if self.wblock.is_some() {
|
||||
self.active_modal = Some(super::ModalKind::WriteBlock);
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
@@ -6110,6 +6416,15 @@ impl OpenCADStudio {
|
||||
.collect();
|
||||
block_def.error_message = None;
|
||||
self.active_modal = Some(super::ModalKind::BlockDefinition);
|
||||
} else if let Some(ref mut wblock) = self.wblock {
|
||||
wblock.selected_handles = self.tabs[i]
|
||||
.scene
|
||||
.selected_entities()
|
||||
.into_iter()
|
||||
.map(|(h, _)| h)
|
||||
.collect();
|
||||
wblock.error_message = None;
|
||||
self.active_modal = Some(super::ModalKind::WriteBlock);
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ impl OpenCADStudio {
|
||||
Some(K::DrawingUnits) => crate::t!("Drawing Units").into_owned(),
|
||||
Some(K::BlockDefinition) => crate::t!("Block Definition").into_owned(),
|
||||
Some(K::XrefAttach) => crate::t!("Attach External Reference").into_owned(),
|
||||
Some(K::WriteBlock) => crate::t!("Write Block").into_owned(),
|
||||
Some(K::GeometricTolerance) => crate::t!("Geometric Tolerance").into_owned(),
|
||||
Some(K::DraftingSettings) => crate::t!("Drafting Settings").into_owned(),
|
||||
Some(K::AutoConstrainSettings) => crate::t!("Constraint Settings").into_owned(),
|
||||
@@ -514,6 +515,12 @@ impl OpenCADStudio {
|
||||
crate::ui::window::xref_attach::view_window(state, flow)
|
||||
})
|
||||
}
|
||||
super::super::ModalKind::WriteBlock => {
|
||||
let state = self.wblock.as_ref()?;
|
||||
sized_flow(ex, 440, 395, |flow| {
|
||||
crate::ui::window::wblock::view_window(state, flow)
|
||||
})
|
||||
}
|
||||
super::super::ModalKind::GeometricTolerance => {
|
||||
let state = self.geometric_tolerance.as_ref()?;
|
||||
sized_flow(ex, 670, 530, |flow| {
|
||||
|
||||
@@ -3,6 +3,17 @@
|
||||
|
||||
pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static str)> {
|
||||
match source {
|
||||
"Entire drawing" => Some(("common", "entire-drawing")),
|
||||
"Delete from drawing" => Some(("common", "delete-from-drawing")),
|
||||
"Destination" => Some(("common", "destination")),
|
||||
"File name and path:" => Some(("common", "file-name-and-path")),
|
||||
"Insert units:" => Some(("common", "insert-units-label")),
|
||||
"Please select or enter a block name." => Some(("common", "wblock-err-no-block-name")),
|
||||
"Block \"{}\" does not exist in drawing." => Some(("common", "wblock-err-block-not-found")),
|
||||
"Please specify a file name and path." => Some(("common", "wblock-err-no-path")),
|
||||
"Cannot write to the current drawing file." => Some(("common", "wblock-err-current-drawing")),
|
||||
"WBLOCK writes objects, a block, or the entire drawing to a new drawing file." => Some(("common", "wblock-help-info")),
|
||||
"WBLOCK Specify insertion base point:" => Some(("insert", "wblock-specify-insertion-base-point")),
|
||||
"Auto Constrain" => Some(("common", "auto-constrain")),
|
||||
"Delete Constraints" => Some(("common", "delete-constraints")),
|
||||
"Dimensional" => Some(("common", "dimensional")),
|
||||
|
||||
@@ -157,3 +157,109 @@ pub fn normalize_to_origin(out: &mut CadDocument) {
|
||||
crate::scene::view::dispatch::apply_transform(entity, &shift);
|
||||
}
|
||||
}
|
||||
|
||||
/// One-shot point picker for the Write Block dialog's "Pick point" button.
|
||||
pub struct WblockPickBasePointCommand;
|
||||
|
||||
impl crate::command::CadCommand for WblockPickBasePointCommand {
|
||||
fn name(&self) -> &'static str {
|
||||
"WBLOCK"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
crate::t!("WBLOCK Specify insertion base point:").into_owned()
|
||||
}
|
||||
|
||||
fn on_point(&mut self, pt: glam::DVec3) -> crate::command::CmdResult {
|
||||
crate::command::CmdResult::Dispatch(format!("WBLOCK_POINT_PICKED {} {} {}", pt.x, pt.y, pt.z))
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> crate::command::CmdResult {
|
||||
crate::command::CmdResult::Dispatch("WBLOCK_POINT_CANCELLED".to_string())
|
||||
}
|
||||
|
||||
fn on_escape(&mut self) -> crate::command::CmdResult {
|
||||
crate::command::CmdResult::Dispatch("WBLOCK_POINT_CANCELLED".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a standalone `CadDocument` from an explicit list of entity handles,
|
||||
/// applying `base_point` translation and `unit` insertion units.
|
||||
pub fn extract_entities_to_doc_with_base(
|
||||
src: &CadDocument,
|
||||
handles: &[acadrust::Handle],
|
||||
base_point: glam::DVec3,
|
||||
unit: i16,
|
||||
) -> Result<CadDocument, String> {
|
||||
let mut out = CadDocument::new();
|
||||
out.header.insertion_units = unit;
|
||||
extract_entities_into(src, handles, &mut out)?;
|
||||
if base_point != glam::DVec3::ZERO {
|
||||
let shift = crate::command::EntityTransform::Affine(
|
||||
acadrust::types::Transform::from_translation(acadrust::types::Vector3::new(
|
||||
-base_point.x,
|
||||
-base_point.y,
|
||||
-base_point.z,
|
||||
)),
|
||||
);
|
||||
for entity in out.entities_mut() {
|
||||
crate::scene::view::dispatch::apply_transform(entity, &shift);
|
||||
}
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use acadrust::entities::Line;
|
||||
use acadrust::types::Vector3;
|
||||
|
||||
#[test]
|
||||
fn test_extract_entities_with_base_point_and_units() {
|
||||
let mut doc = CadDocument::new();
|
||||
let mut line = Line::new();
|
||||
line.start = Vector3::new(10.0, 20.0, 0.0);
|
||||
line.end = Vector3::new(30.0, 40.0, 0.0);
|
||||
let h = doc.add_entity(EntityType::Line(line)).unwrap();
|
||||
|
||||
let out = extract_entities_to_doc_with_base(
|
||||
&doc,
|
||||
&[h],
|
||||
glam::DVec3::new(10.0, 20.0, 0.0),
|
||||
4, // Millimeters
|
||||
)
|
||||
.expect("extract should succeed");
|
||||
|
||||
assert_eq!(out.header.insertion_units, 4);
|
||||
assert_eq!(out.entities().count(), 1);
|
||||
let e = out.entities().next().unwrap();
|
||||
if let EntityType::Line(l) = e {
|
||||
assert!((l.start.x - 0.0).abs() < 1e-6);
|
||||
assert!((l.start.y - 0.0).abs() < 1e-6);
|
||||
assert!((l.end.x - 20.0).abs() < 1e-6);
|
||||
assert!((l.end.y - 20.0).abs() < 1e-6);
|
||||
} else {
|
||||
panic!("Expected Line entity");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_block_to_doc() {
|
||||
let mut doc = CadDocument::new();
|
||||
let mut line = Line::new();
|
||||
line.start = Vector3::new(1.0, 2.0, 0.0);
|
||||
line.end = Vector3::new(3.0, 4.0, 0.0);
|
||||
let h = doc.add_entity(EntityType::Line(line)).unwrap();
|
||||
|
||||
let mut block_record = acadrust::tables::BlockRecord::new("MY_BLOCK".to_string());
|
||||
block_record.entity_handles.push(h);
|
||||
let _ = doc.block_records.add(block_record);
|
||||
|
||||
let out = extract_block_to_doc(&doc, "MY_BLOCK").expect("block extract should succeed");
|
||||
assert_eq!(out.entities().count(), 1);
|
||||
|
||||
assert!(extract_block_to_doc(&doc, "NON_EXISTENT").is_err());
|
||||
}
|
||||
}
|
||||
|
||||
+35
-1
@@ -7,10 +7,44 @@
|
||||
|
||||
use crate::app::Message;
|
||||
use crate::ui::style::common::muted_style;
|
||||
use iced::widget::{button, container, pick_list, row, text, text_input, Space};
|
||||
use iced::widget::{button, container, pick_list, radio, row, text, text_input, Space};
|
||||
use iced::{Background, Border, Element, Length, Theme};
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// Standard dialog footer action button (OK, Cancel, Apply, Close, Help, etc.),
|
||||
/// matching the Drafting Settings / Options appearance: 12px text, [6, 18] padding,
|
||||
/// themed primary or secondary style.
|
||||
pub fn dialog_button<'a>(
|
||||
label: impl text::IntoFragment<'a>,
|
||||
on_press: Message,
|
||||
primary: bool,
|
||||
) -> button::Button<'a, Message> {
|
||||
button(text(label).size(12))
|
||||
.on_press(on_press)
|
||||
.padding([6, 18])
|
||||
.style(if primary {
|
||||
button::primary
|
||||
} else {
|
||||
button::secondary
|
||||
})
|
||||
}
|
||||
|
||||
/// Unified radio button helper ensuring consistent 16px size for exact pixel-grid concentric alignment.
|
||||
pub fn form_radio<'a, T>(
|
||||
label: impl Into<String>,
|
||||
value: T,
|
||||
selected: Option<T>,
|
||||
on_click: impl Fn(T) -> Message + 'a,
|
||||
) -> radio::Radio<'a, Message>
|
||||
where
|
||||
T: Copy + Eq + 'a,
|
||||
{
|
||||
radio(label, value, selected, on_click)
|
||||
.size(16)
|
||||
.spacing(6)
|
||||
.text_size(11)
|
||||
}
|
||||
|
||||
/// Width of the label column in a `label : control` row.
|
||||
pub const LABEL_WIDTH: f32 = 92.0;
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ pub fn view_window<'a>(
|
||||
Some(relative),
|
||||
Message::PointStyleSizeRelative,
|
||||
)
|
||||
.size(15)
|
||||
.size(16)
|
||||
.text_size(13),
|
||||
radio(
|
||||
t!("Set Size in Absolute Units"),
|
||||
@@ -176,7 +176,7 @@ pub fn view_window<'a>(
|
||||
Some(relative),
|
||||
Message::PointStyleSizeRelative,
|
||||
)
|
||||
.size(15)
|
||||
.size(16)
|
||||
.text_size(13),
|
||||
]
|
||||
.spacing(6);
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::fmt;
|
||||
|
||||
use acadrust::Handle;
|
||||
use iced::widget::{
|
||||
button, checkbox, column, combo_box, container, mouse_area, pick_list, radio, row, stack, text,
|
||||
button, checkbox, column, combo_box, container, mouse_area, pick_list, row, stack, text,
|
||||
text_editor, text_input, Space,
|
||||
};
|
||||
use iced::{Background, Border, Element, Fill, Length, Theme};
|
||||
@@ -14,7 +14,7 @@ use crate::app::Message;
|
||||
use crate::modules::draw::units;
|
||||
use crate::t;
|
||||
use crate::ui::style::common::muted_style;
|
||||
use crate::ui::style::form::{button_style, field_style};
|
||||
use crate::ui::style::form::{button_style, dialog_button, field_style, form_radio};
|
||||
|
||||
static ICON_PICK_POINT: &[u8] = include_bytes!("../../../assets/icons/blocks/pick_point.svg");
|
||||
static ICON_SELECT_OBJECTS: &[u8] =
|
||||
@@ -353,33 +353,24 @@ pub fn view_window<'a>(
|
||||
let btns_row = row![sel_obj_btn, qsel_btn].spacing(5).align_y(iced::Center);
|
||||
|
||||
let radios = column![
|
||||
radio(
|
||||
form_radio(
|
||||
t!("Retain"),
|
||||
BlockObjectMode::Retain,
|
||||
Some(state.object_mode),
|
||||
Message::BlockDefObjectMode,
|
||||
)
|
||||
.size(15)
|
||||
.spacing(5)
|
||||
.text_size(11),
|
||||
radio(
|
||||
),
|
||||
form_radio(
|
||||
t!("Convert to block"),
|
||||
BlockObjectMode::Convert,
|
||||
Some(state.object_mode),
|
||||
Message::BlockDefObjectMode,
|
||||
)
|
||||
.size(15)
|
||||
.spacing(5)
|
||||
.text_size(11),
|
||||
radio(
|
||||
),
|
||||
form_radio(
|
||||
t!("Delete"),
|
||||
BlockObjectMode::Delete,
|
||||
Some(state.object_mode),
|
||||
Message::BlockDefObjectMode,
|
||||
)
|
||||
.size(15)
|
||||
.spacing(5)
|
||||
.text_size(11),
|
||||
),
|
||||
]
|
||||
.spacing(2);
|
||||
|
||||
@@ -580,20 +571,11 @@ pub fn view_window<'a>(
|
||||
// ── Footer Bar ────────────────────────────────────────────────────────────
|
||||
let actions = row![
|
||||
Space::new().width(Fill),
|
||||
button(text(t!("OK")).size(11))
|
||||
.on_press(Message::BlockDefApply)
|
||||
.style(button_style(true))
|
||||
.padding([4, 16]),
|
||||
button(text(t!("Cancel")).size(11))
|
||||
.on_press(Message::CloseModal)
|
||||
.style(button_style(false))
|
||||
.padding([4, 12]),
|
||||
button(text(t!("Help")).size(11))
|
||||
.on_press(Message::BlockDefHelp)
|
||||
.style(button_style(false))
|
||||
.padding([4, 12]),
|
||||
dialog_button(t!("OK"), Message::BlockDefApply, true),
|
||||
dialog_button(t!("Cancel"), Message::CloseModal, false),
|
||||
dialog_button(t!("Help"), Message::BlockDefHelp, false),
|
||||
]
|
||||
.spacing(6)
|
||||
.spacing(8)
|
||||
.align_y(iced::Center);
|
||||
|
||||
// ── Error Banner ──────────────────────────────────────────────────────────
|
||||
@@ -664,15 +646,9 @@ pub fn view_window<'a>(
|
||||
.align_x(iced::alignment::Horizontal::Center),
|
||||
Space::new().height(16),
|
||||
row![
|
||||
button(text(t!("Yes")).size(12))
|
||||
.on_press(Message::BlockDefConfirmRedefine(true))
|
||||
.padding([6, 20])
|
||||
.style(button_style(false)),
|
||||
dialog_button(t!("Yes"), Message::BlockDefConfirmRedefine(true), false),
|
||||
// Default / safe focus on "No"
|
||||
button(text(t!("No")).size(12))
|
||||
.on_press(Message::BlockDefConfirmRedefine(false))
|
||||
.padding([6, 22])
|
||||
.style(button_style(true)),
|
||||
dialog_button(t!("No"), Message::BlockDefConfirmRedefine(false), true),
|
||||
]
|
||||
.spacing(12)
|
||||
.align_y(iced::Center),
|
||||
|
||||
@@ -27,3 +27,4 @@ pub mod named_parameters;
|
||||
pub mod xref_attach;
|
||||
pub mod xref_help;
|
||||
pub mod xref_manager;
|
||||
pub mod wblock;
|
||||
@@ -0,0 +1,492 @@
|
||||
//! Write Block (WBLOCK) dialog window — write a block, selected entities, or entire drawing to an external DWG/DXF file.
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use acadrust::Handle;
|
||||
use iced::widget::{
|
||||
button, column, combo_box, container, pick_list, row, text, text_input, Space,
|
||||
};
|
||||
use iced::{Background, Border, Element, Fill, Length, Theme};
|
||||
|
||||
use crate::app::Message;
|
||||
use crate::modules::draw::units;
|
||||
use crate::t;
|
||||
use crate::ui::style::form::{button_style, dialog_button, field_style, form_radio};
|
||||
|
||||
static ICON_PICK_POINT: &[u8] = include_bytes!("../../../assets/icons/blocks/pick_point.svg");
|
||||
static ICON_SELECT_OBJECTS: &[u8] =
|
||||
include_bytes!("../../../assets/icons/blocks/select_objects.svg");
|
||||
static ICON_QUICK_SELECT: &[u8] = include_bytes!("../../../assets/icons/blocks/quick_select.svg");
|
||||
static ICON_WARN: &[u8] = include_bytes!("../../../assets/icons/ui/warning_triangle.svg");
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum WblockSourceMode {
|
||||
Block,
|
||||
EntireDrawing,
|
||||
Objects,
|
||||
}
|
||||
|
||||
impl Default for WblockSourceMode {
|
||||
fn default() -> Self {
|
||||
WblockSourceMode::Objects
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum WblockObjectMode {
|
||||
Retain,
|
||||
Convert,
|
||||
Delete,
|
||||
}
|
||||
|
||||
impl Default for WblockObjectMode {
|
||||
fn default() -> Self {
|
||||
WblockObjectMode::Retain
|
||||
}
|
||||
}
|
||||
|
||||
/// Dropdown entry for the Unit picker.
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct UnitChoice {
|
||||
pub code: i16,
|
||||
pub label: &'static str,
|
||||
}
|
||||
|
||||
impl fmt::Display for UnitChoice {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let name = crate::i18n::translate(self.label);
|
||||
f.write_str(name.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
/// The Write Block dialog's state.
|
||||
pub struct WblockState {
|
||||
pub source_mode: WblockSourceMode,
|
||||
pub block_name: String,
|
||||
pub existing_blocks: Vec<String>,
|
||||
pub block_combo: combo_box::State<String>,
|
||||
|
||||
pub base_point_x: String,
|
||||
pub base_point_y: String,
|
||||
pub base_point_z: String,
|
||||
|
||||
pub selected_handles: Vec<Handle>,
|
||||
pub object_mode: WblockObjectMode,
|
||||
|
||||
pub file_path: String,
|
||||
pub unit: i16,
|
||||
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
impl Clone for WblockState {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
source_mode: self.source_mode,
|
||||
block_name: self.block_name.clone(),
|
||||
existing_blocks: self.existing_blocks.clone(),
|
||||
block_combo: self.block_combo.clone(),
|
||||
base_point_x: self.base_point_x.clone(),
|
||||
base_point_y: self.base_point_y.clone(),
|
||||
base_point_z: self.base_point_z.clone(),
|
||||
selected_handles: self.selected_handles.clone(),
|
||||
object_mode: self.object_mode,
|
||||
file_path: self.file_path.clone(),
|
||||
unit: self.unit,
|
||||
error_message: self.error_message.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WblockState {
|
||||
pub fn new(
|
||||
existing_blocks: Vec<String>,
|
||||
pre_selected: Vec<Handle>,
|
||||
default_unit: i16,
|
||||
default_path: String,
|
||||
) -> Self {
|
||||
let default_block = existing_blocks.first().cloned().unwrap_or_default();
|
||||
Self {
|
||||
source_mode: WblockSourceMode::Objects,
|
||||
block_name: default_block,
|
||||
block_combo: combo_box::State::new(existing_blocks.clone()),
|
||||
existing_blocks,
|
||||
base_point_x: "0.00".to_string(),
|
||||
base_point_y: "0.00".to_string(),
|
||||
base_point_z: "0.00".to_string(),
|
||||
selected_handles: pre_selected,
|
||||
object_mode: WblockObjectMode::Retain,
|
||||
file_path: default_path,
|
||||
unit: default_unit,
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_base_point(&self) -> glam::DVec3 {
|
||||
let x = self.base_point_x.trim().parse::<f64>().unwrap_or(0.0);
|
||||
let y = self.base_point_y.trim().parse::<f64>().unwrap_or(0.0);
|
||||
let z = self.base_point_z.trim().parse::<f64>().unwrap_or(0.0);
|
||||
glam::DVec3::new(x, y, z)
|
||||
}
|
||||
}
|
||||
|
||||
fn group<'a>(
|
||||
title: impl Into<String>,
|
||||
body: impl Into<Element<'a, Message>>,
|
||||
height: impl Into<Length>,
|
||||
) -> Element<'a, Message> {
|
||||
container(
|
||||
column![
|
||||
text(title.into())
|
||||
.size(11)
|
||||
.style(|theme: &Theme| text::Style {
|
||||
color: Some(theme.palette().background.strongest.text.scale_alpha(0.85)),
|
||||
}),
|
||||
body.into(),
|
||||
]
|
||||
.spacing(4),
|
||||
)
|
||||
.padding([5, 8])
|
||||
.width(Fill)
|
||||
.height(height)
|
||||
.style(|theme: &Theme| container::Style {
|
||||
border: Border {
|
||||
width: 1.0,
|
||||
radius: 4.0.into(),
|
||||
color: theme.palette().background.strong.color,
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn view_window<'a>(
|
||||
state: &'a WblockState,
|
||||
sizing: crate::ui::modal::ModalSizing,
|
||||
) -> Element<'a, Message> {
|
||||
let is_objects = state.source_mode == WblockSourceMode::Objects;
|
||||
let is_block = state.source_mode == WblockSourceMode::Block;
|
||||
|
||||
// ── Source: Block Radio & Dropdown ─────────────────────────────────────────
|
||||
let block_radio = form_radio(
|
||||
t!("Block:"),
|
||||
WblockSourceMode::Block,
|
||||
Some(state.source_mode),
|
||||
Message::WblockSourceMode,
|
||||
);
|
||||
|
||||
let block_dropdown: Element<'a, Message> = if is_block {
|
||||
combo_box(
|
||||
&state.block_combo,
|
||||
"",
|
||||
if state.block_name.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(&state.block_name)
|
||||
},
|
||||
|chosen: String| Message::WblockBlockSelect(chosen),
|
||||
)
|
||||
.on_input(Message::WblockBlockName)
|
||||
.size(11)
|
||||
.padding([2, 5])
|
||||
.width(Fill)
|
||||
.into()
|
||||
} else {
|
||||
crate::ui::read_only::field(&state.block_name, 11.0, Fill)
|
||||
};
|
||||
|
||||
let block_row = row![block_radio, block_dropdown]
|
||||
.spacing(8)
|
||||
.width(Fill)
|
||||
.align_y(iced::Center);
|
||||
|
||||
let entire_drawing_radio = form_radio(
|
||||
t!("Entire drawing"),
|
||||
WblockSourceMode::EntireDrawing,
|
||||
Some(state.source_mode),
|
||||
Message::WblockSourceMode,
|
||||
);
|
||||
|
||||
let objects_radio = form_radio(
|
||||
t!("Objects"),
|
||||
WblockSourceMode::Objects,
|
||||
Some(state.source_mode),
|
||||
Message::WblockSourceMode,
|
||||
);
|
||||
|
||||
// ── Source: Base Point Sub-group ──────────────────────────────────────────
|
||||
let pick_pt_icon = crate::ui::icons::semantic(ICON_PICK_POINT, 14.0);
|
||||
let mut pick_pt_btn = button(
|
||||
row![pick_pt_icon, text(t!("Pick point")).size(11)]
|
||||
.spacing(6)
|
||||
.align_y(iced::Center),
|
||||
)
|
||||
.padding([3, 10]);
|
||||
|
||||
if is_objects {
|
||||
pick_pt_btn = pick_pt_btn
|
||||
.on_press(Message::WblockPickPoint)
|
||||
.style(button_style(false));
|
||||
} else {
|
||||
pick_pt_btn = pick_pt_btn.style(button_style(false));
|
||||
}
|
||||
|
||||
let coord_row = |axis: &'static str, val: &'a str, on_input: fn(String) -> Message| {
|
||||
let input: Element<'a, Message> = if is_objects {
|
||||
text_input("", val)
|
||||
.on_input(on_input)
|
||||
.on_submit(Message::WblockApply)
|
||||
.style(field_style)
|
||||
.size(11)
|
||||
.padding([2, 5])
|
||||
.width(Fill)
|
||||
.into()
|
||||
} else {
|
||||
crate::ui::read_only::field(val, 11.0, Fill)
|
||||
};
|
||||
row![
|
||||
text(axis)
|
||||
.size(11)
|
||||
.style(|theme: &Theme| text::Style {
|
||||
color: Some(theme.palette().background.strongest.text.scale_alpha(0.85)),
|
||||
})
|
||||
.width(Length::Fixed(16.0)),
|
||||
input,
|
||||
]
|
||||
.spacing(4)
|
||||
.align_y(iced::Center)
|
||||
};
|
||||
|
||||
let base_point_group = group(
|
||||
t!("Base point").into_owned(),
|
||||
column![
|
||||
pick_pt_btn,
|
||||
Space::new().height(3),
|
||||
coord_row("X:", &state.base_point_x, Message::WblockBaseX),
|
||||
coord_row("Y:", &state.base_point_y, Message::WblockBaseY),
|
||||
coord_row("Z:", &state.base_point_z, Message::WblockBaseZ),
|
||||
]
|
||||
.spacing(3),
|
||||
Length::Fixed(142.0),
|
||||
);
|
||||
|
||||
// ── Source: Objects Sub-group ─────────────────────────────────────────────
|
||||
let sel_obj_icon = crate::ui::icons::semantic(ICON_SELECT_OBJECTS, 14.0);
|
||||
let mut sel_obj_btn = button(
|
||||
row![sel_obj_icon, text(t!("Select objects")).size(11)]
|
||||
.spacing(6)
|
||||
.align_y(iced::Center),
|
||||
)
|
||||
.padding([3, 8]);
|
||||
|
||||
let qsel_icon = crate::ui::icons::semantic(ICON_QUICK_SELECT, 14.0);
|
||||
let mut qsel_btn = button(qsel_icon).padding([3, 6]);
|
||||
|
||||
if is_objects {
|
||||
sel_obj_btn = sel_obj_btn
|
||||
.on_press(Message::WblockSelectObjects)
|
||||
.style(button_style(false));
|
||||
qsel_btn = qsel_btn
|
||||
.on_press(Message::WblockQuickSelect)
|
||||
.style(button_style(false));
|
||||
} else {
|
||||
sel_obj_btn = sel_obj_btn.style(button_style(false));
|
||||
qsel_btn = qsel_btn.style(button_style(false));
|
||||
}
|
||||
|
||||
let obj_btns_row = row![sel_obj_btn, qsel_btn]
|
||||
.spacing(5)
|
||||
.align_y(iced::Center);
|
||||
|
||||
let object_radios = column![
|
||||
form_radio(
|
||||
t!("Retain"),
|
||||
WblockObjectMode::Retain,
|
||||
if is_objects { Some(state.object_mode) } else { None },
|
||||
Message::WblockObjectMode,
|
||||
),
|
||||
form_radio(
|
||||
t!("Convert to block"),
|
||||
WblockObjectMode::Convert,
|
||||
if is_objects { Some(state.object_mode) } else { None },
|
||||
Message::WblockObjectMode,
|
||||
),
|
||||
form_radio(
|
||||
t!("Delete from drawing"),
|
||||
WblockObjectMode::Delete,
|
||||
if is_objects { Some(state.object_mode) } else { None },
|
||||
Message::WblockObjectMode,
|
||||
),
|
||||
]
|
||||
.spacing(3);
|
||||
|
||||
let count = state.selected_handles.len();
|
||||
let status_row: Element<'a, Message> = if !is_objects {
|
||||
Space::new().height(14).into()
|
||||
} else if count == 0 {
|
||||
row![
|
||||
crate::ui::icons::semantic(ICON_WARN, 13.0),
|
||||
text(t!("No objects selected"))
|
||||
.size(10)
|
||||
.style(|theme: &Theme| text::Style {
|
||||
color: Some(theme.palette().warning.base.color),
|
||||
}),
|
||||
]
|
||||
.spacing(5)
|
||||
.align_y(iced::Center)
|
||||
.into()
|
||||
} else {
|
||||
row![text(crate::tf!("{count} objects selected"))
|
||||
.size(10)
|
||||
.style(|theme: &Theme| text::Style {
|
||||
color: Some(theme.palette().primary.base.color),
|
||||
}),]
|
||||
.spacing(5)
|
||||
.align_y(iced::Center)
|
||||
.into()
|
||||
};
|
||||
|
||||
let objects_subgroup = group(
|
||||
t!("Objects").into_owned(),
|
||||
column![obj_btns_row, Space::new().height(2), object_radios, Space::new().height(2), status_row,]
|
||||
.spacing(2),
|
||||
Length::Fixed(142.0),
|
||||
);
|
||||
|
||||
let sub_panels = row![base_point_group, objects_subgroup]
|
||||
.spacing(8)
|
||||
.width(Fill);
|
||||
|
||||
let source_group = group(
|
||||
t!("Source").into_owned(),
|
||||
column![
|
||||
block_row,
|
||||
entire_drawing_radio,
|
||||
objects_radio,
|
||||
Space::new().height(4),
|
||||
sub_panels,
|
||||
]
|
||||
.spacing(4),
|
||||
Length::Shrink,
|
||||
);
|
||||
|
||||
// ── Destination Group ─────────────────────────────────────────────────────
|
||||
let file_input = text_input("", &state.file_path)
|
||||
.on_input(Message::WblockFilePath)
|
||||
.on_submit(Message::WblockApply)
|
||||
.style(field_style)
|
||||
.size(11)
|
||||
.padding([3, 6])
|
||||
.width(Fill);
|
||||
|
||||
let browse_btn = button(
|
||||
container(text("...").size(11))
|
||||
.width(Fill)
|
||||
.align_x(iced::alignment::Horizontal::Center),
|
||||
)
|
||||
.width(Length::Fixed(28.0))
|
||||
.on_press(Message::WblockBrowsePath)
|
||||
.style(button::secondary)
|
||||
.padding([3, 0]);
|
||||
|
||||
let path_row = row![file_input, browse_btn].spacing(5).align_y(iced::Center);
|
||||
|
||||
let unit_options: Vec<UnitChoice> = units::all()
|
||||
.map(|(code, label)| UnitChoice { code, label })
|
||||
.collect();
|
||||
|
||||
let selected_unit = unit_options
|
||||
.iter()
|
||||
.find(|choice| choice.code == state.unit)
|
||||
.cloned();
|
||||
|
||||
let unit_picker = pick_list(selected_unit, unit_options, |choice| choice.to_string())
|
||||
.on_select(|choice| Message::WblockUnit(choice.code))
|
||||
.text_size(11)
|
||||
.padding([2, 5])
|
||||
.width(Fill);
|
||||
|
||||
let units_row = row![
|
||||
text(t!("Insert units:"))
|
||||
.size(11)
|
||||
.style(|theme: &Theme| text::Style {
|
||||
color: Some(theme.palette().background.strongest.text.scale_alpha(0.85)),
|
||||
}),
|
||||
Space::new().width(8),
|
||||
unit_picker,
|
||||
Space::new().width(Length::Fixed(33.0)),
|
||||
]
|
||||
.spacing(4)
|
||||
.align_y(iced::Center);
|
||||
|
||||
let destination_group = group(
|
||||
t!("Destination").into_owned(),
|
||||
column![
|
||||
text(t!("File name and path:"))
|
||||
.size(11)
|
||||
.style(|theme: &Theme| text::Style {
|
||||
color: Some(theme.palette().background.strongest.text.scale_alpha(0.85)),
|
||||
}),
|
||||
path_row,
|
||||
Space::new().height(4),
|
||||
units_row,
|
||||
]
|
||||
.spacing(3),
|
||||
Length::Shrink,
|
||||
);
|
||||
|
||||
// ── Footer Bar ────────────────────────────────────────────────────────────
|
||||
let actions = row![
|
||||
Space::new().width(Fill),
|
||||
dialog_button(t!("OK"), Message::WblockApply, true),
|
||||
dialog_button(t!("Cancel"), Message::CloseModal, false),
|
||||
dialog_button(t!("Help"), Message::WblockHelp, false),
|
||||
]
|
||||
.spacing(8)
|
||||
.align_y(iced::Center);
|
||||
|
||||
// ── Error Banner ──────────────────────────────────────────────────────────
|
||||
let mut main_column = column![source_group, destination_group, actions,]
|
||||
.spacing(8)
|
||||
.padding([8, 10])
|
||||
.width(sizing.width);
|
||||
|
||||
if let Some(err) = &state.error_message {
|
||||
let err_banner = container(
|
||||
row![
|
||||
crate::ui::icons::semantic(ICON_WARN, 16.0),
|
||||
text(err.clone())
|
||||
.size(11)
|
||||
.style(|theme: &Theme| text::Style {
|
||||
color: Some(theme.palette().background.strongest.text),
|
||||
}),
|
||||
Space::new().width(Fill),
|
||||
button(text("×").size(12))
|
||||
.on_press(Message::WblockDismissError)
|
||||
.style(button_style(false))
|
||||
.padding([1, 6]),
|
||||
]
|
||||
.spacing(8)
|
||||
.align_y(iced::Center),
|
||||
)
|
||||
.padding([6, 10])
|
||||
.style(|theme: &Theme| container::Style {
|
||||
background: Some(Background::Color(
|
||||
theme.palette().danger.base.color.scale_alpha(0.18),
|
||||
)),
|
||||
border: Border {
|
||||
width: 1.0,
|
||||
radius: 4.0.into(),
|
||||
color: theme.palette().danger.base.color,
|
||||
},
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
main_column = column![err_banner, main_column]
|
||||
.spacing(6)
|
||||
.width(sizing.width)
|
||||
.padding(10);
|
||||
}
|
||||
|
||||
main_column.into()
|
||||
}
|
||||
Reference in new issue
Block a user