Merge pull request #1489 from ramox81/codex/pdf-dialog-redesign

PDF dialogs: own look with cards, segmented choices and chips
This commit is contained in:
Hakan Seven committed 2026-09-25 15:19:07 +03:00
commit 2801ac2007
25 files changed
+603 -390

No files matched your search

+7
View File
@@ -3531,6 +3531,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3518,6 +3518,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3516,6 +3516,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3519,6 +3519,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3519,6 +3519,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3520,6 +3520,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3519,6 +3519,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3518,6 +3518,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3519,6 +3519,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3507,6 +3507,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3518,6 +3518,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3518,6 +3518,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3509,6 +3509,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3518,6 +3518,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3517,6 +3517,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3518,6 +3518,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3519,6 +3519,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3520,6 +3520,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3493,6 +3493,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Ekleme noktasını ekranda belirt .pdfui-specify-insertion-point-on-screen = Ekleme noktasını ekranda belirt
.pdfui-page-size-size = Sayfa boyutu: __ocs_fmt_0__ .pdfui-page-size-size = Sayfa boyutu: __ocs_fmt_0__
.pdfui-total-count = Toplam: __ocs_fmt_0__ .pdfui-total-count = Toplam: __ocs_fmt_0__
.pdfui-pages = Sayfalar
.pdfui-placement = Yerleşim
.pdfui-on-screen = Ekranda
.pdfui-file-details = Dosya bilgisi
.pdfui-page-count = __ocs_fmt_0__ sayfa
.pdfui-selected-pages = Seçili sayfalar: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ katman, __ocs_fmt_1__ gizli
.pdfui-page = Sayfa: .pdfui-page = Sayfa:
.pdfui-page-to-import = İçe aktarılacak sayfa .pdfui-page-to-import = İçe aktarılacak sayfa
.pdfui-infer-linetypes-from-collinear-dashes = Aynı doğrultudaki kesiklerden çizgi tipi çıkar .pdfui-infer-linetypes-from-collinear-dashes = Aynı doğrultudaki kesiklerden çizgi tipi çıkar
+7
View File
@@ -3506,6 +3506,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+7
View File
@@ -3518,6 +3518,13 @@ insert =
.pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen .pdfui-specify-insertion-point-on-screen = Specify insertion point on-screen
.pdfui-page-size-size = Page size: __ocs_fmt_0__ .pdfui-page-size-size = Page size: __ocs_fmt_0__
.pdfui-total-count = Total: __ocs_fmt_0__ .pdfui-total-count = Total: __ocs_fmt_0__
.pdfui-pages = Pages
.pdfui-placement = Placement
.pdfui-on-screen = On screen
.pdfui-file-details = File details
.pdfui-page-count = __ocs_fmt_0__ pages
.pdfui-selected-pages = Selected pages: __ocs_fmt_0__
.pdfui-layer-summary = __ocs_fmt_0__ layers, __ocs_fmt_1__ hidden
.pdfui-page = Page: .pdfui-page = Page:
.pdfui-page-to-import = Page to import .pdfui-page-to-import = Page to import
.pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes .pdfui-infer-linetypes-from-collinear-dashes = Infer linetypes from collinear dashes
+3 -1
View File
@@ -306,7 +306,9 @@ impl OpenCADStudio {
Some(at) => { Some(at) => {
t.hidden.remove(at); t.hidden.remove(at);
} }
None => t.hidden.push(layer), // Only a layer the file has can be turned off.
None if t.layers.contains(&layer) => t.hidden.push(layer),
None => {}
} }
} }
} }
+4 -5
View File
@@ -514,26 +514,25 @@ impl OpenCADStudio {
} }
super::super::ModalKind::PdfAttach => { super::super::ModalKind::PdfAttach => {
let state = self.pdf_attach.as_ref()?; let state = self.pdf_attach.as_ref()?;
let height = if state.details { 520 } else { 440 }; sized_flow(ex, 880, 540, |flow| {
sized_flow(ex, 820, height, |flow| {
crate::ui::window::pdf_dialogs::view_attach(state, flow) crate::ui::window::pdf_dialogs::view_attach(state, flow)
}) })
} }
super::super::ModalKind::UnderlayLayers => { super::super::ModalKind::UnderlayLayers => {
let state = self.underlay_layers.as_ref()?; let state = self.underlay_layers.as_ref()?;
sized_flow(ex, 500, 500, |flow| { sized_flow(ex, 460, 520, |flow| {
crate::ui::window::pdf_dialogs::view_layers(state, flow) crate::ui::window::pdf_dialogs::view_layers(state, flow)
}) })
} }
super::super::ModalKind::PdfImportSettings => { super::super::ModalKind::PdfImportSettings => {
let settings = self.pdf_import_settings.as_ref()?; let settings = self.pdf_import_settings.as_ref()?;
sized_flow(ex, 600, 360, |flow| { sized_flow(ex, 640, 380, |flow| {
crate::ui::window::pdf_dialogs::view_import_settings(settings, flow) crate::ui::window::pdf_dialogs::view_import_settings(settings, flow)
}) })
} }
super::super::ModalKind::PdfImportFile => { super::super::ModalKind::PdfImportFile => {
let state = self.pdf_import_file.as_ref()?; let state = self.pdf_import_file.as_ref()?;
sized_flow(ex, 900, 560, |flow| { sized_flow(ex, 960, 560, |flow| {
crate::ui::window::pdf_dialogs::view_import_file(state, flow) crate::ui::window::pdf_dialogs::view_import_file(state, flow)
}) })
} }
+7
View File
@@ -2997,6 +2997,13 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
"Page to import" => Some(("insert", "pdfui-page-to-import")), "Page to import" => Some(("insert", "pdfui-page-to-import")),
"Page:" => Some(("insert", "pdfui-page")), "Page:" => Some(("insert", "pdfui-page")),
"Total: {count}" => Some(("insert", "pdfui-total-count")), "Total: {count}" => Some(("insert", "pdfui-total-count")),
"Pages" => Some(("insert", "pdfui-pages")),
"Placement" => Some(("insert", "pdfui-placement")),
"On screen" => Some(("insert", "pdfui-on-screen")),
"File details" => Some(("insert", "pdfui-file-details")),
"{count} pages" => Some(("insert", "pdfui-page-count")),
"Selected pages: {pages}" => Some(("insert", "pdfui-selected-pages")),
"{count} layers, {hidden} hidden" => Some(("insert", "pdfui-layer-summary")),
"Page size: {size}" => Some(("insert", "pdfui-page-size-size")), "Page size: {size}" => Some(("insert", "pdfui-page-size-size")),
"Specify insertion point on-screen" => Some(("insert", "pdfui-specify-insertion-point-on-screen")), "Specify insertion point on-screen" => Some(("insert", "pdfui-specify-insertion-point-on-screen")),
"Scale:" => Some(("insert", "pdfui-scale")), "Scale:" => Some(("insert", "pdfui-scale")),
+442 -384
View File
@@ -1,5 +1,6 @@
//! PDF dialogs: Attach PDF Underlay (pages, path type, insertion, scale, //! PDF dialogs: Attach PDF Underlay (pages, path type, insertion, scale,
//! rotation), Underlay Layers, PDF Import Settings and Import PDF. //! rotation), Underlay Layers, PDF Import Settings and Import PDF, built
//! from cards, segmented choices and toggle chips.
use std::fmt; use std::fmt;
@@ -14,8 +15,7 @@ use crate::io::xref_model::Pathtype;
use crate::modules::insert::pdf_import::{ImportLayers, PdfImportSettings}; use crate::modules::insert::pdf_import::{ImportLayers, PdfImportSettings};
use crate::t; use crate::t;
use crate::ui::style::common::muted_style; use crate::ui::style::common::muted_style;
use crate::ui::style::form::{button_style, dialog_button, field_style, form_radio}; use crate::ui::style::form::{button_style, dialog_button, field_style};
use crate::ui::window::block_definition::{group, labeled_checkbox};
/// One edit in any of the PDF dialogs. /// One edit in any of the PDF dialogs.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -115,7 +115,7 @@ pub struct PageThumb {
pub image: Option<image::Handle>, pub image: Option<image::Handle>,
} }
/// Thumbnails of every page, about 100 px wide. /// Thumbnails of every page, about 220 px wide (sharp at preview size).
// ponytail: all pages are rasterised when the dialog opens; lazy per-row // ponytail: all pages are rasterised when the dialog opens; lazy per-row
// thumbnails if files with hundreds of pages matter. // thumbnails if files with hundreds of pages matter.
pub fn page_thumbs(path: &str) -> Vec<PageThumb> { pub fn page_thumbs(path: &str) -> Vec<PageThumb> {
@@ -125,7 +125,7 @@ pub fn page_thumbs(path: &str) -> Vec<PageThumb> {
.map(|n| { .map(|n| {
let label = n.to_string(); let label = n.to_string();
let image = page_size_inches(path, &label).and_then(|(w, h)| { let image = page_size_inches(path, &label).and_then(|(w, h)| {
let dpi = (100.0 / w.max(h).max(0.1)) as f32; let dpi = (220.0 / w.max(h).max(0.1)) as f32;
let page = rasterize_page_at_dpi(path, &label, dpi)?; let page = rasterize_page_at_dpi(path, &label, dpi)?;
Some(image::Handle::from_rgba(page.width, page.height, page.pixels.to_vec())) Some(image::Handle::from_rgba(page.width, page.height, page.pixels.to_vec()))
}); });
@@ -158,23 +158,159 @@ pub fn click_page(selected: &mut Vec<usize>, anchor: &mut usize, page: usize, ct
} }
} }
fn frame_style(theme: &Theme) -> container::Style { // ── Shared look ────────────────────────────────────────────────────────────
//
// The PDF dialogs are built from rounded cards on a slightly raised surface,
// accent-coloured card titles, segmented choices and toggle chips, with the
// help button on the left of the footer and the named action on the right.
fn accent_text(theme: &Theme) -> text::Style {
text::Style {
color: Some(theme.palette().primary.base.color),
}
}
fn card_style(theme: &Theme) -> container::Style {
container::Style { container::Style {
background: Some(Background::Color(theme.palette().background.base.color)), background: Some(Background::Color(theme.palette().background.weak.color)),
border: Border { border: Border {
width: 1.0, width: 0.0,
radius: 2.0.into(), radius: 8.0.into(),
color: theme.palette().background.strong.color, color: iced::Color::TRANSPARENT,
}, },
..Default::default() ..Default::default()
} }
} }
fn page_grid<'a>( fn well_style(theme: &Theme) -> container::Style {
container::Style {
background: Some(Background::Color(theme.palette().background.base.color)),
border: Border {
width: 0.0,
radius: 6.0.into(),
color: iced::Color::TRANSPARENT,
},
..Default::default()
}
}
/// A titled card.
fn card<'a>(title: String, content: impl Into<Element<'a, Message>>) -> Element<'a, Message> {
container(
column![text(title.to_uppercase()).size(10).style(accent_text), content.into()].spacing(8),
)
.padding([10, 12])
.width(Fill)
.style(card_style)
.into()
}
/// One choice out of a few, as joined buttons.
fn segmented<'a, T: Copy + PartialEq + 'a>(
options: Vec<(T, String)>,
current: T,
on: fn(T) -> PdfDialogMsg,
) -> Element<'a, Message> {
let buttons = options.into_iter().map(|(value, label)| {
button(text(label).size(11).width(Fill).align_x(iced::Center))
.on_press(msg(on(value)))
.style(button_style(value == current))
.padding([5, 6])
.width(Fill)
.into()
});
container(iced::widget::Row::with_children(buttons.collect::<Vec<_>>()).spacing(2))
.padding(2)
.width(Fill)
.style(well_style)
.into()
}
/// A switch shown as a chip: filled with a tick while on.
fn chip<'a>(label: String, on: bool, message: Message) -> Element<'a, Message> {
let label = if on { format!("\u{2713} {label}") } else { label };
button(text(label).size(11))
.on_press(message)
.style(button_style(on))
.padding([4, 10])
.into()
}
/// A labelled field on one row; read-only while `enabled` is false.
fn field<'a>(
label: String,
value: &'a str,
enabled: bool,
label_width: f32,
on_input: impl Fn(String) -> Message + 'a,
) -> Element<'a, Message> {
let mut input = text_input("", value)
.size(11)
.padding([4, 8])
.width(Fill)
.style(field_style);
if enabled {
input = input.on_input(on_input);
}
row![
text(label).size(11).style(muted_style).width(Length::Fixed(label_width)),
input
]
.spacing(6)
.align_y(iced::Center)
.into()
}
/// A label and a value on one line; a long value keeps its end.
fn info_line<'a>(label: String, value: &'a str) -> Element<'a, Message> {
const MAX: usize = 70;
let count = value.chars().count();
let shown = if count > MAX {
format!("…{}", value.chars().skip(count - (MAX - 1)).collect::<String>())
} else {
value.to_string()
};
row![
text(label).size(11).style(muted_style).width(Length::Fixed(96.0)),
text(shown).size(11).width(Fill).wrapping(iced::advanced::text::Wrapping::None),
]
.spacing(6)
.into()
}
/// Help on the left, extra buttons, then Cancel and the named action.
fn footer<'a>(
help: &'static str,
extra: Option<Element<'a, Message>>,
action: std::borrow::Cow<'static, str>,
ok: PdfDialogMsg,
) -> Element<'a, Message> {
let mut left = row![button(text("?").size(12))
.on_press(msg(PdfDialogMsg::Help(help)))
.style(button_style(false))
.padding([5, 11])]
.spacing(6)
.align_y(iced::Center);
if let Some(extra) = extra {
left = left.push(extra);
}
row![
left,
Space::new().width(Fill),
dialog_button(t!("Cancel"), Message::CloseModal, false),
dialog_button(action, msg(ok), true),
]
.spacing(6)
.align_y(iced::Center)
.into()
}
/// Page thumbnails as cards; the chosen ones framed in the accent colour
/// with a ticked page number.
fn page_tiles<'a>(
pages: &'a [PageThumb], pages: &'a [PageThumb],
selected: &[usize], selected: &[usize],
on_click: fn(usize) -> PdfDialogMsg, on_click: fn(usize) -> PdfDialogMsg,
height: f32,
) -> Element<'a, Message> { ) -> Element<'a, Message> {
let tiles = pages.iter().enumerate().map(|(index, page)| { let tiles = pages.iter().enumerate().map(|(index, page)| {
let chosen = selected.contains(&index); let chosen = selected.contains(&index);
@@ -182,92 +318,52 @@ fn page_grid<'a>(
Some(handle) => image(handle.clone()).width(Fill).height(Fill).into(), Some(handle) => image(handle.clone()).width(Fill).height(Fill).into(),
None => Space::new().width(Fill).height(Fill).into(), None => Space::new().width(Fill).height(Fill).into(),
}; };
let number = if chosen {
format!("\u{2713} {}", page.label)
} else {
page.label.clone()
};
let tile = column![ let tile = column![
container(picture) container(picture)
.width(Length::Fixed(100.0)) .width(Length::Fixed(132.0))
.height(Length::Fixed(60.0)) .height(Length::Fixed(86.0))
.padding(2) .padding(4)
.style(move |theme: &Theme| container::Style { .style(move |theme: &Theme| container::Style {
background: Some(Background::Color(iced::Color::WHITE)), background: Some(Background::Color(iced::Color::WHITE)),
border: Border { border: Border {
width: if chosen { 2.0 } else { 1.0 }, width: if chosen { 2.5 } else { 0.0 },
radius: 1.0.into(), radius: 6.0.into(),
color: if chosen { color: theme.palette().primary.base.color,
theme.palette().primary.base.color
} else {
theme.palette().background.strong.color
},
}, },
..Default::default() ..Default::default()
}), }),
container(text(page.label.clone()).size(11)) container(text(number).size(11).style(move |theme: &Theme| text::Style {
.width(Length::Fixed(100.0)) color: Some(if chosen {
.align_x(iced::Center) theme.palette().primary.base.color
.style(move |theme: &Theme| container::Style { } else {
background: chosen theme.palette().background.base.text.scale_alpha(0.68)
.then(|| Background::Color(theme.palette().primary.weak.color)),
..Default::default()
}), }),
}))
.width(Length::Fixed(132.0))
.align_x(iced::Center),
] ]
.spacing(1); .spacing(4);
button(tile) button(tile)
.on_press(msg(on_click(index))) .on_press(msg(on_click(index)))
.padding(2) .padding(4)
.style(|_: &Theme, _| button::Style::default()) .style(|_: &Theme, _| button::Style::default())
.into() .into()
}); });
container(scrollable( scrollable(
iced::widget::Row::with_children(tiles.collect::<Vec<_>>()) iced::widget::Row::with_children(tiles.collect::<Vec<_>>())
.spacing(8) .spacing(6)
.wrap() .wrap()
.vertical_spacing(8), .vertical_spacing(6),
)) )
.padding(6) .height(Fill)
.width(Fill)
.height(Length::Fixed(height))
.style(frame_style)
.into() .into()
} }
fn value_field<'a>(
label: String,
value: &'a str,
enabled: bool,
label_width: f32,
on_input: impl Fn(String) -> Message + 'a,
) -> Element<'a, Message> {
let mut field = text_input("", value)
.size(11)
.padding([3, 6])
.width(Fill)
.style(field_style);
if enabled {
field = field.on_input(on_input);
}
row![
text(label).size(11).style(muted_style).width(Length::Fixed(label_width)),
field
]
.spacing(6)
.align_y(iced::Center)
.into()
}
fn read_only<'a>(label: String, value: &'a str, label_width: f32) -> Element<'a, Message> {
value_field(label, value, false, label_width, |_| Message::Noop)
}
fn footer<'a>(ok: PdfDialogMsg, help: &'static str) -> iced::widget::Row<'a, Message> {
row![
Space::new().width(Fill),
dialog_button(t!("OK"), msg(ok), true),
dialog_button(t!("Cancel"), Message::CloseModal, false),
dialog_button(t!("Help"), msg(PdfDialogMsg::Help(help)), false),
]
.spacing(6)
.align_y(iced::Center)
}
// ── Attach PDF Underlay ──────────────────────────────────────────────────── // ── Attach PDF Underlay ────────────────────────────────────────────────────
/// Choices the Attach dialog keeps for its next opening. /// Choices the Attach dialog keeps for its next opening.
@@ -377,144 +473,117 @@ pub fn view_attach<'a>(
state: &'a PdfAttachState, state: &'a PdfAttachState,
sizing: crate::ui::modal::ModalSizing, sizing: crate::ui::modal::ModalSizing,
) -> Element<'a, Message> { ) -> Element<'a, Message> {
// File: the attached PDFs to pick from, Browse, and the page count.
let name_combo = combo_box( let name_combo = combo_box(
&state.name_combo, &state.name_combo,
"", "",
(!state.name.is_empty()).then_some(&state.name), (!state.name.is_empty()).then_some(&state.name),
|chosen: String| msg(PdfDialogMsg::AttachName(chosen)), |chosen: String| msg(PdfDialogMsg::AttachName(chosen)),
) )
.size(11) .size(12)
.padding([3, 6]) .padding([5, 8])
.width(Fill); .width(Fill);
let name_section = column![ let count = container(
text(t!("Name:")).size(11).style(muted_style), text(crate::tf!("{count} pages", count = state.pages.len())).size(11).style(accent_text),
row![ )
name_combo, .padding([4, 10])
button(text(t!("Browse...")).size(11)) .style(well_style);
.on_press(msg(PdfDialogMsg::AttachBrowse)) let file = row![
.style(button_style(false)) name_combo,
.padding([4, 12]) count,
.width(Length::Fixed(96.0)), button(text(t!("Browse...")).size(11))
] .on_press(msg(PdfDialogMsg::AttachBrowse))
.spacing(8) .style(button_style(false))
.align_y(iced::Center), .padding([5, 12]),
] ]
.spacing(3); .spacing(8)
let pages = group(
t!("Select one or more pages from the PDF file:").into_owned(),
page_grid(&state.pages, &state.selected, PdfDialogMsg::AttachPage, 250.0),
Length::Shrink,
);
let path_type = group(
t!("Path type").into_owned(),
pick_list(Some(state.path_type), PathTypeChoice::ALL, |c| c.to_string())
.on_select(|v| msg(PdfDialogMsg::AttachPathType(v)))
.text_size(11)
.padding([3, 6])
.width(Fill),
Length::Shrink,
);
let insert_enabled = !state.insert_on_screen;
let insertion = group(
t!("Insertion point").into_owned(),
column![
labeled_checkbox(t!("Specify On-screen"), state.insert_on_screen, |v| msg(
PdfDialogMsg::AttachInsertOnScreen(v)
)),
value_field("X:".into(), &state.insert[0], insert_enabled, 16.0, |v| msg(
PdfDialogMsg::AttachInsert(0, v)
)),
value_field("Y:".into(), &state.insert[1], insert_enabled, 16.0, |v| msg(
PdfDialogMsg::AttachInsert(1, v)
)),
value_field("Z:".into(), &state.insert[2], insert_enabled, 16.0, |v| msg(
PdfDialogMsg::AttachInsert(2, v)
)),
]
.spacing(5),
Length::Shrink,
);
let middle = column![path_type, insertion].spacing(6).width(Length::FillPortion(1));
let mut scale_field = text_input("", &state.scale)
.size(11)
.padding([3, 6])
.width(Fill)
.style(field_style);
if !state.scale_on_screen {
scale_field = scale_field.on_input(|v| msg(PdfDialogMsg::AttachScale(v)));
}
let scale = group(
t!("Scale").into_owned(),
column![
labeled_checkbox(t!("Specify On-screen"), state.scale_on_screen, |v| msg(
PdfDialogMsg::AttachScaleOnScreen(v)
)),
scale_field,
]
.spacing(5),
Length::Shrink,
);
let rotation = group(
t!("Rotation").into_owned(),
column![
labeled_checkbox(t!("Specify On-screen"), state.rotation_on_screen, |v| msg(
PdfDialogMsg::AttachRotationOnScreen(v)
)),
value_field(
t!("Angle:").into_owned(),
&state.rotation,
!state.rotation_on_screen,
44.0,
|v| msg(PdfDialogMsg::AttachRotation(v))
),
]
.spacing(5),
Length::Shrink,
);
let right = column![scale, rotation].spacing(6).width(Length::FillPortion(1));
let body = row![
container(pages).width(Length::FillPortion(1)),
middle,
right
]
.spacing(6)
.width(Fill);
let details: Element<'a, Message> = if state.details {
group(
t!("Location").into_owned(),
column![
read_only(t!("Found in:").into_owned(), &state.found_in, 92.0),
read_only(t!("Saved path:").into_owned(), &state.saved_path, 92.0),
read_only(t!("Page size:").into_owned(), &state.page_size, 92.0),
]
.spacing(5),
Length::Shrink,
)
} else {
Space::new().height(0).into()
};
let details_label = if state.details {
t!("Hide Details")
} else {
t!("Show Details")
};
let footer = row![dialog_button(
details_label,
msg(PdfDialogMsg::AttachDetails(!state.details)),
false
)]
.push(footer(PdfDialogMsg::AttachOk, "attach"))
.align_y(iced::Center); .align_y(iced::Center);
column![name_section, body, details, footer] // Pages: the thumbnails, then which ones are chosen.
.spacing(6) let chosen = state.page_labels().join(", ");
.padding([8, 10]) let pages = card(
t!("Pages").into_owned(),
column![
container(page_tiles(&state.pages, &state.selected, PdfDialogMsg::AttachPage))
.padding(6)
.height(Length::Fixed(226.0))
.width(Fill)
.style(well_style),
text(crate::tf!("Selected pages: {pages}", pages = chosen)).size(11).style(muted_style),
]
.spacing(6),
);
// Placement: insertion point, scale and rotation, each with an
// "On screen" chip that leaves the value to the command line.
let on_screen = t!("On screen").into_owned();
let insert_enabled = !state.insert_on_screen;
let xyz = row![
field("X".into(), &state.insert[0], insert_enabled, 12.0, |v| msg(PdfDialogMsg::AttachInsert(0, v))),
field("Y".into(), &state.insert[1], insert_enabled, 12.0, |v| msg(PdfDialogMsg::AttachInsert(1, v))),
field("Z".into(), &state.insert[2], insert_enabled, 12.0, |v| msg(PdfDialogMsg::AttachInsert(2, v))),
]
.spacing(8);
let heading = |label: std::borrow::Cow<'static, str>, on: bool, message: Message| {
row![
text(label).size(11).width(Fill),
chip(on_screen.clone(), on, message)
]
.align_y(iced::Center)
};
let placement = card(
t!("Placement").into_owned(),
column![
heading(
t!("Insertion point"),
state.insert_on_screen,
msg(PdfDialogMsg::AttachInsertOnScreen(!state.insert_on_screen))
),
xyz,
heading(
t!("Scale"),
state.scale_on_screen,
msg(PdfDialogMsg::AttachScaleOnScreen(!state.scale_on_screen))
),
field(String::new(), &state.scale, !state.scale_on_screen, 0.0, |v| msg(PdfDialogMsg::AttachScale(v))),
heading(
t!("Rotation"),
state.rotation_on_screen,
msg(PdfDialogMsg::AttachRotationOnScreen(!state.rotation_on_screen))
),
field(String::new(), &state.rotation, !state.rotation_on_screen, 0.0, |v| msg(PdfDialogMsg::AttachRotation(v))),
]
.spacing(6),
);
let path = card(
t!("Path type").into_owned(),
segmented(
PathTypeChoice::ALL.iter().map(|c| (*c, c.to_string())).collect(),
state.path_type,
PdfDialogMsg::AttachPathType,
),
);
let details = card(
t!("File details").into_owned(),
column![
info_line(t!("Found in:").into_owned(), &state.found_in),
info_line(t!("Saved path:").into_owned(), &state.saved_path),
info_line(t!("Page size:").into_owned(), &state.page_size),
]
.spacing(4),
);
let body = row![
column![pages, details].spacing(8).width(Length::FillPortion(3)),
column![placement, path].spacing(8).width(Length::FillPortion(2)),
]
.spacing(10);
column![file, body, footer("attach", None, t!("Attach"), PdfDialogMsg::AttachOk)]
.spacing(10)
.padding([10, 12])
.width(sizing.width) .width(sizing.width)
.into() .into()
} }
@@ -543,28 +612,24 @@ pub fn view_layers<'a>(
) -> Element<'a, Message> { ) -> Element<'a, Message> {
let names: Vec<String> = state.targets.iter().map(|t| t.name.clone()).collect(); let names: Vec<String> = state.targets.iter().map(|t| t.name.clone()).collect();
let target = state.targets.get(state.current); let target = state.targets.get(state.current);
let reference = row![ let underlay = pick_list(target.map(|t| t.name.clone()), names, |n: &String| n.clone())
text(t!("Reference name:")).size(11).width(Length::Fixed(110.0)), .on_select(|n| msg(PdfDialogMsg::LayersUnderlay(n)))
pick_list(target.map(|t| t.name.clone()), names, |n: &String| n.clone()) .text_size(12)
.on_select(|n| msg(PdfDialogMsg::LayersUnderlay(n))) .padding([5, 8])
.text_size(11) .width(Fill);
.padding([3, 6])
.width(Fill),
]
.spacing(6)
.align_y(iced::Center);
let search = text_input(t!("Search for layer").as_ref(), &state.search) let search = text_input(t!("Search for layer").as_ref(), &state.search)
.on_input(|s| msg(PdfDialogMsg::LayersSearch(s))) .on_input(|s| msg(PdfDialogMsg::LayersSearch(s)))
.size(11) .size(11)
.padding([3, 6]) .padding([5, 8])
.width(Length::Fixed(220.0)) .width(Fill)
.style(field_style); .style(field_style);
let header = row![ let (total, hidden) = target.map_or((0, 0), |t| (t.layers.len(), t.hidden.len()));
text(t!("On")).size(11).style(muted_style).width(Length::Fixed(44.0)), let summary = text(crate::tf!("{count} layers, {hidden} hidden", count = total, hidden = hidden))
text(t!("Name")).size(11).style(muted_style), .size(11)
] .style(muted_style);
.padding([4, 8]);
// Each layer: its name and an On / Off switch.
let body: Element<'a, Message> = match target { let body: Element<'a, Message> = match target {
Some(t) if !t.layers.is_empty() => { Some(t) if !t.layers.is_empty() => {
let needle = state.search.to_lowercase(); let needle = state.search.to_lowercase();
@@ -574,135 +639,118 @@ pub fn view_layers<'a>(
.filter(|name| needle.is_empty() || name.to_lowercase().contains(&needle)) .filter(|name| needle.is_empty() || name.to_lowercase().contains(&needle))
.map(|name| { .map(|name| {
let on = !t.hidden.contains(name); let on = !t.hidden.contains(name);
let bulb = button(crate::ui::icons::semantic( let switch = button(
crate::ui::icons::layer_visible(on), text(if on { t!("On") } else { t!("Off") })
14.0, .size(11)
)) .width(Fill)
.align_x(iced::Center),
)
.on_press(msg(PdfDialogMsg::LayersToggle(name.clone()))) .on_press(msg(PdfDialogMsg::LayersToggle(name.clone())))
.padding([0, 4]) .style(button_style(on))
.style(|_: &Theme, _| button::Style::default()); .padding([3, 6])
row![ .width(Length::Fixed(64.0));
container(bulb).width(Length::Fixed(44.0)), container(
text(name.clone()).size(11) row![text(name.clone()).size(12).width(Fill), switch]
] .align_y(iced::Center),
.padding([2, 8]) )
.align_y(iced::Center) .padding([5, 10])
.style(well_style)
.into() .into()
}); });
scrollable(iced::widget::Column::with_children(rows.collect::<Vec<_>>())) scrollable(iced::widget::Column::with_children(rows.collect::<Vec<_>>()).spacing(4))
.height(Fill) .height(Fill)
.into() .into()
} }
_ => container(text(t!("This file does not contain any layers.")).size(11)) _ => container(text(t!("This file does not contain any layers.")).size(11).style(muted_style))
.width(Fill) .width(Fill)
.height(Fill) .height(Fill)
.align_x(iced::Center) .align_x(iced::Center)
.align_y(iced::Center) .align_y(iced::Center)
.into(), .into(),
}; };
let list = container(column![header, body])
.width(Fill)
.height(Length::Fixed(300.0))
.style(frame_style);
column![ column![
text(t!("Select an underlay to view its layers.")).size(11), card(t!("Underlay").into_owned(), underlay),
reference, card(
search, t!("Layers").into_owned(),
list, column![search, summary, container(body).height(Length::Fixed(250.0))].spacing(6)
footer(PdfDialogMsg::LayersOk, "layers"), ),
footer("layers", None, t!("Apply"), PdfDialogMsg::LayersOk),
] ]
.spacing(8) .spacing(10)
.padding([8, 10]) .padding([10, 12])
.width(sizing.width) .width(sizing.width)
.into() .into()
} }
// ── PDF Import Settings ──────────────────────────────────────────────────── // ── PDF Import Settings ────────────────────────────────────────────────────
fn settings_groups<'a>(s: &'a PdfImportSettings) -> (Element<'a, Message>, Element<'a, Message>, Element<'a, Message>) { /// Content as chips, layers as a segmented choice, options as chips.
let fills: Element<'a, Message> = if s.vector { fn settings_cards<'a>(s: &'a PdfImportSettings) -> (Element<'a, Message>, Element<'a, Message>, Element<'a, Message>) {
labeled_checkbox(t!("Solid fills"), s.fills, |v| msg(PdfDialogMsg::Fills(v))) let fills = if s.vector {
chip(t!("Solid fills").into_owned(), s.fills, msg(PdfDialogMsg::Fills(!s.fills)))
} else { } else {
labeled_checkbox(t!("Solid fills"), s.fills, move |_| Message::Noop) chip(t!("Solid fills").into_owned(), s.fills, Message::Noop)
}; };
let data = group( let content = card(
t!("PDF data to import").into_owned(), t!("PDF data to import").into_owned(),
column![ row![
labeled_checkbox(t!("Vector geometry"), s.vector, |v| msg(PdfDialogMsg::Vector(v))), chip(t!("Vector geometry").into_owned(), s.vector, msg(PdfDialogMsg::Vector(!s.vector))),
container(fills).padding(iced::Padding { left: 20.0, ..Default::default() }), fills,
labeled_checkbox(t!("TrueType text"), s.text, |v| msg(PdfDialogMsg::Text(v))), chip(t!("TrueType text").into_owned(), s.text, msg(PdfDialogMsg::Text(!s.text))),
labeled_checkbox(t!("Raster images"), s.raster, |v| msg(PdfDialogMsg::Raster(v))), chip(t!("Raster images").into_owned(), s.raster, msg(PdfDialogMsg::Raster(!s.raster))),
] ]
.spacing(6), .spacing(6)
Length::Fill, .wrap()
.vertical_spacing(6),
); );
let layer_radio = |label: std::borrow::Cow<'static, str>, value: ImportLayers| { let layers = card(
form_radio(label, value, Some(s.layers), |v| msg(PdfDialogMsg::Layers(v)))
};
let layers = group(
t!("Layers").into_owned(), t!("Layers").into_owned(),
column![ segmented(
layer_radio(t!("Use PDF layers"), ImportLayers::Pdf), vec![
layer_radio(t!("Create object layers"), ImportLayers::Object), (ImportLayers::Pdf, t!("Use PDF layers").into_owned()),
layer_radio(t!("Current layer"), ImportLayers::Current), (ImportLayers::Object, t!("Create object layers").into_owned()),
] (ImportLayers::Current, t!("Current layer").into_owned()),
.spacing(6), ],
Length::Fill, s.layers,
PdfDialogMsg::Layers,
),
); );
let options = group( let options = card(
t!("Import options").into_owned(), t!("Import options").into_owned(),
column![ row![
labeled_checkbox(t!("Import as block"), s.as_block, |v| msg(PdfDialogMsg::AsBlock(v))), chip(t!("Import as block").into_owned(), s.as_block, msg(PdfDialogMsg::AsBlock(!s.as_block))),
labeled_checkbox(t!("Join line and arc segments"), s.join, |v| msg( chip(t!("Join line and arc segments").into_owned(), s.join, msg(PdfDialogMsg::Join(!s.join))),
PdfDialogMsg::Join(v) chip(t!("Convert solid fills to hatches").into_owned(), s.hatches, msg(PdfDialogMsg::Hatches(!s.hatches))),
)), chip(t!("Apply lineweight properties").into_owned(), s.lineweights, msg(PdfDialogMsg::Lineweights(!s.lineweights))),
labeled_checkbox(t!("Convert solid fills to hatches"), s.hatches, |v| msg( chip(t!("Infer linetypes from collinear dashes").into_owned(), s.linetypes, msg(PdfDialogMsg::Linetypes(!s.linetypes))),
PdfDialogMsg::Hatches(v)
)),
labeled_checkbox(t!("Apply lineweight properties"), s.lineweights, |v| msg(
PdfDialogMsg::Lineweights(v)
)),
labeled_checkbox(t!("Infer linetypes from collinear dashes"), s.linetypes, |v| msg(
PdfDialogMsg::Linetypes(v)
)),
] ]
.spacing(6), .spacing(6)
Length::Shrink, .wrap()
.vertical_spacing(6),
); );
(data, layers, options) (content, layers, options)
} }
pub fn view_import_settings<'a>( pub fn view_import_settings<'a>(
settings: &'a PdfImportSettings, settings: &'a PdfImportSettings,
sizing: crate::ui::modal::ModalSizing, sizing: crate::ui::modal::ModalSizing,
) -> Element<'a, Message> { ) -> Element<'a, Message> {
let (data, layers, options) = settings_groups(settings); let (content, layers, options) = settings_cards(settings);
let side_button = |label: std::borrow::Cow<'static, str>, on: Message, accent: bool| { let more = button(text(t!("Options...")).size(11))
button(text(label).size(11).width(Fill).align_x(iced::Center)) .on_press(msg(PdfDialogMsg::Options))
.on_press(on) .style(button_style(false))
.style(button_style(accent)) .padding([5, 12]);
.padding([4, 12]) column![
.width(Length::Fixed(110.0)) content,
}; layers,
let left = column![ options,
row![data, layers].spacing(8).height(Length::Fixed(140.0)), footer("settings", Some(more.into()), t!("Save"), PdfDialogMsg::SettingsOk),
options
] ]
.spacing(8) .spacing(10)
.width(Fill); .padding([10, 12])
let right = column![ .width(sizing.width)
side_button(t!("OK"), msg(PdfDialogMsg::SettingsOk), true), .into()
side_button(t!("Cancel"), Message::CloseModal, false),
side_button(t!("Options..."), msg(PdfDialogMsg::Options), false),
side_button(t!("Help"), msg(PdfDialogMsg::Help("settings")), false),
]
.spacing(8);
row![left, right]
.spacing(10)
.padding([8, 10])
.width(sizing.width)
.into()
} }
// ── Import PDF (File) ────────────────────────────────────────────────────── // ── Import PDF (File) ──────────────────────────────────────────────────────
@@ -727,100 +775,110 @@ pub fn view_import_file<'a>(
.file_name() .file_name()
.map(|n| n.to_string_lossy().into_owned()) .map(|n| n.to_string_lossy().into_owned())
.unwrap_or_default(); .unwrap_or_default();
let file_row = row![ let file = row![
text(t!("File name:")).size(11).width(Length::Fixed(70.0)), container(text(file_name).size(12))
text_input("", &file_name) .padding([6, 10])
.size(11)
.padding([3, 6])
.width(Fill) .width(Fill)
.style(field_style), .style(well_style),
button(text(t!("Browse...")).size(11)) button(text(t!("Browse...")).size(11))
.on_press(msg(PdfDialogMsg::ImportBrowse)) .on_press(msg(PdfDialogMsg::ImportBrowse))
.style(button_style(false)) .style(button_style(false))
.padding([4, 12]) .padding([5, 12]),
.width(Length::Fixed(96.0)),
] ]
.spacing(8) .spacing(8)
.align_y(iced::Center); .align_y(iced::Center);
let selected = [state.selected]; // One page at a time: a large preview with previous / next.
let page_group = group( let count = state.pages.len();
t!("Page to import").into_owned(), let preview: Element<'a, Message> = match state.pages.get(state.selected).and_then(|p| p.image.clone()) {
Some(handle) => image(handle).width(Fill).height(Fill).into(),
None => Space::new().width(Fill).height(Fill).into(),
};
let step = |label: &'static str, to: Option<usize>| {
button(text(label).size(14))
.on_press_maybe(to.map(|p| msg(PdfDialogMsg::ImportPage(p))))
.style(button_style(false))
.padding([2, 12])
};
let navigator = row![
step("\u{2039}", state.selected.checked_sub(1)),
Space::new().width(Fill),
text_input("", &state.page_text)
.on_input(|s| msg(PdfDialogMsg::ImportPageText(s)))
.size(11)
.padding([3, 6])
.width(Length::Fixed(48.0))
.style(field_style),
text(format!("/ {count}")).size(11).style(muted_style),
Space::new().width(Fill),
step("\u{203a}", (state.selected + 1 < count).then_some(state.selected + 1)),
]
.spacing(6)
.align_y(iced::Center);
let page = card(
t!("Pages").into_owned(),
column![ column![
container(preview)
.padding(8)
.height(Length::Fixed(300.0))
.width(Fill)
.style(|_: &Theme| container::Style {
background: Some(Background::Color(iced::Color::WHITE)),
border: Border { width: 0.0, radius: 6.0.into(), color: iced::Color::TRANSPARENT },
..Default::default()
}),
navigator,
row![ row![
text(t!("Page:")).size(11), text(crate::tf!("Page size: {size}", size = state.page_size.clone())).size(11).style(muted_style),
text_input("", &state.page_text)
.on_input(|s| msg(PdfDialogMsg::ImportPageText(s)))
.size(11)
.padding([3, 6])
.width(Length::Fixed(56.0))
.style(field_style),
text(crate::tf!("Total: {count}", count = state.pages.len()))
.size(11)
.style(muted_style),
]
.spacing(8)
.align_y(iced::Center),
page_grid(&state.pages, &selected, PdfDialogMsg::ImportPage, 300.0),
row![
text(crate::tf!("Page size: {size}", size = state.page_size.clone()))
.size(11)
.style(muted_style),
Space::new().width(Fill), Space::new().width(Fill),
text(crate::tf!("PDF scale: {scale}:1", scale = state.scale.trim())) text(crate::tf!("PDF scale: {scale}:1", scale = state.scale.trim())).size(11).style(muted_style),
.size(11)
.style(muted_style),
], ],
] ]
.spacing(6), .spacing(8),
Length::Shrink,
); );
let location = group( let placement = card(
t!("Location").into_owned(), t!("Placement").into_owned(),
column![ column![
labeled_checkbox(t!("Specify insertion point on-screen"), state.insert_on_screen, |v| {
msg(PdfDialogMsg::ImportInsertOnScreen(v))
}),
row![ row![
text(t!("Scale:")).size(11).style(muted_style), text(t!("Insertion point")).size(11).width(Fill),
text_input("", &state.scale) chip(
.on_input(|s| msg(PdfDialogMsg::ImportScale(s))) t!("On screen").into_owned(),
.size(11) state.insert_on_screen,
.padding([3, 6]) msg(PdfDialogMsg::ImportInsertOnScreen(!state.insert_on_screen))
.width(Length::Fixed(80.0)) ),
.style(field_style), ]
Space::new().width(Length::Fixed(20.0)), .align_y(iced::Center),
text(t!("Rotation:")).size(11).style(muted_style), field(t!("Scale").into_owned(), &state.scale, true, 60.0, |s| msg(PdfDialogMsg::ImportScale(s))),
pick_list(Some(state.rotation), RotationChoice::ALL, |c| c.to_string()) row![
.on_select(|v| msg(PdfDialogMsg::ImportRotation(v))) text(t!("Rotation")).size(11).style(muted_style).width(Length::Fixed(60.0)),
.text_size(11) segmented(
.padding([3, 6]) RotationChoice::ALL.iter().map(|r| (*r, format!("{}\u{b0}", r.0))).collect(),
.width(Length::Fixed(76.0)), state.rotation,
PdfDialogMsg::ImportRotation,
),
] ]
.spacing(6) .spacing(6)
.align_y(iced::Center), .align_y(iced::Center),
] ]
.spacing(6), .spacing(8),
Length::Shrink,
); );
let (data, layers, options) = settings_groups(&state.settings); let (content, layers, options) = settings_cards(&state.settings);
let right = column![ let right = scrollable(column![placement, content, layers, options].spacing(8)).height(Fill);
location, let body = row![
row![data, layers].spacing(8).height(Length::Fixed(140.0)), container(page).width(Length::FillPortion(1)),
options container(right).width(Length::FillPortion(1)),
] ]
.spacing(8) .spacing(10)
.width(Length::FillPortion(1)); .height(Length::Fixed(420.0));
let body = row![container(page_group).width(Length::FillPortion(1)), right].spacing(8);
let footer = row![dialog_button(t!("Options..."), msg(PdfDialogMsg::Options), false)] let more = button(text(t!("Options...")).size(11))
.push(footer(PdfDialogMsg::ImportOk, "import")) .on_press(msg(PdfDialogMsg::Options))
.align_y(iced::Center); .style(button_style(false))
.padding([5, 12]);
column![file_row, body, footer] column![file, body, footer("import", Some(more.into()), t!("Import"), PdfDialogMsg::ImportOk)]
.spacing(8) .spacing(10)
.padding([8, 10]) .padding([10, 12])
.width(sizing.width) .width(sizing.width)
.into() .into()
} }