mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-13 13:52:31 +00:00
fix(ui): dropdown menus grow back after a search with no matches (#1917)
* fix(ui): font menus grow back after a search with no matches Every combo box is craft_ui::ComboBox (craft-libs pinned at 62bb0e1d), whose menu follows its contents' height while open (egui#5225); clippy.toml bans egui::ComboBox. The Font menu splits into a header (search field, filters) and a list (font_menu_header, font_menu_list). Font fields show it in a craft_ui::combo::Menu and the style dialogs' Font Family combo boxes in ComboBox::show_ui_with_header, so only the rows scroll and the search field stays in place. The blank and Parent's Font rows sit in the header, above the search. * chore(deps): craft-libs 60d60d48 (dropdown fixes) * chore(deps): craft-libs 4d7b82f7 (dropdown fixes) * chore(deps): craft-libs 92d392cf (#387 merged) * chore(xtask): pdf-deps expects craft-libs 92d392cf
This commit is contained in:
1 parent
50650f74d7
commit
d77fdf2d4c
26 files changed
+328
-205
No files matched your search
Generated
+19
-19
@@ -1004,7 +1004,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "craft-atomic"
|
name = "craft-atomic"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustix 1.1.5",
|
"rustix 1.1.5",
|
||||||
]
|
]
|
||||||
@@ -1012,7 +1012,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "craft-cms"
|
name = "craft-cms"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rayon",
|
"rayon",
|
||||||
]
|
]
|
||||||
@@ -1020,17 +1020,17 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "craft-docpath"
|
name = "craft-docpath"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "craft-fonts-build"
|
name = "craft-fonts-build"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "craft-i18n"
|
name = "craft-i18n"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fixed_decimal",
|
"fixed_decimal",
|
||||||
"icu_decimal",
|
"icu_decimal",
|
||||||
@@ -1053,7 +1053,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "craft-keymap"
|
name = "craft-keymap"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"craft-i18n",
|
"craft-i18n",
|
||||||
"craft-ui",
|
"craft-ui",
|
||||||
@@ -1065,7 +1065,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "craft-pdf"
|
name = "craft-pdf"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"hayro",
|
"hayro",
|
||||||
@@ -1078,7 +1078,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "craft-prepress"
|
name = "craft-prepress"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"craft-cms",
|
"craft-cms",
|
||||||
"craft-pdf",
|
"craft-pdf",
|
||||||
@@ -1091,7 +1091,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "craft-print"
|
name = "craft-print"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"craft-winprint-gdi",
|
"craft-winprint-gdi",
|
||||||
"miniz_oxide 0.9.1",
|
"miniz_oxide 0.9.1",
|
||||||
@@ -1104,7 +1104,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "craft-ui"
|
name = "craft-ui"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"craft-fonts-build",
|
"craft-fonts-build",
|
||||||
"craft-i18n",
|
"craft-i18n",
|
||||||
@@ -1125,7 +1125,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "craft-update"
|
name = "craft-update"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"dunce",
|
"dunce",
|
||||||
@@ -1150,7 +1150,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "craft-window"
|
name = "craft-window"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"egui",
|
"egui",
|
||||||
"objc2 0.6.5",
|
"objc2 0.6.5",
|
||||||
@@ -2635,7 +2635,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "hayro"
|
name = "hayro"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"hayro-interpret",
|
"hayro-interpret",
|
||||||
@@ -2655,7 +2655,7 @@ checksum = "9f4d0e94ddd48749f06bbe4e5389fb9799a0c45bcaf00495042076ef05e3241a"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "hayro-cmap"
|
name = "hayro-cmap"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"brotli",
|
"brotli",
|
||||||
"hayro-postscript",
|
"hayro-postscript",
|
||||||
@@ -2664,7 +2664,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "hayro-interpret"
|
name = "hayro-interpret"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.2",
|
"bitflags 2.13.2",
|
||||||
"hayro-cmap",
|
"hayro-cmap",
|
||||||
@@ -2682,7 +2682,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "hayro-jbig2"
|
name = "hayro-jbig2"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fearless_simd",
|
"fearless_simd",
|
||||||
"hayro-ccitt",
|
"hayro-ccitt",
|
||||||
@@ -2700,12 +2700,12 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "hayro-postscript"
|
name = "hayro-postscript"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hayro-syntax"
|
name = "hayro-syntax"
|
||||||
version = "0.7.2"
|
version = "0.7.2"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"flate2",
|
"flate2",
|
||||||
"hayro-ccitt",
|
"hayro-ccitt",
|
||||||
@@ -3300,7 +3300,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "krilla"
|
name = "krilla"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
source = "git+https://github.com/storytold/craft-libs?rev=b926b5c03e256c86ca10934f58d03f628810b5b7#b926b5c03e256c86ca10934f58d03f628810b5b7"
|
source = "git+https://github.com/storytold/craft-libs?rev=92d392cff132eaf53e13afff77f38b5c11b73aa0#92d392cff132eaf53e13afff77f38b5c11b73aa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
|
|||||||
+17
-17
@@ -12,12 +12,12 @@ repository = "https://github.com/storytold/designcraft"
|
|||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
# Shared reader and writer; publish the immutable revision before this consumer.
|
# Shared reader and writer; publish the immutable revision before this consumer.
|
||||||
craft-pdf = { git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7", version = "=0.1.0", default-features = false }
|
craft-pdf = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.1.0", default-features = false }
|
||||||
# Shared keyboard bindings: chords, overrides, conflicts, egui dispatch, the Keyboard Shortcuts dialog.
|
# Shared keyboard bindings: chords, overrides, conflicts, egui dispatch, the Keyboard Shortcuts dialog.
|
||||||
craft-keymap = { git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7", version = "=0.1.0", features = ["egui", "ui"] }
|
craft-keymap = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.1.0", features = ["egui", "ui"] }
|
||||||
# Separations, ink coverage and the ink manager; same revision as craft-pdf and the krilla patch.
|
# Separations, ink coverage and the ink manager; same revision as craft-pdf and the krilla patch.
|
||||||
craft-prepress = { git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7", version = "=0.1.0", features = ["flatten"] }
|
craft-prepress = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.1.0", features = ["flatten"] }
|
||||||
craft-update = { git = "https://github.com/storytold/craft-libs", version = "=0.1.0", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7", features = ["egui"] }
|
craft-update = { git = "https://github.com/storytold/craft-libs", version = "=0.1.0", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", features = ["egui"] }
|
||||||
# internal
|
# internal
|
||||||
designcraft-geom = { path = "crates/geom" }
|
designcraft-geom = { path = "crates/geom" }
|
||||||
designcraft-color = { path = "crates/color" }
|
designcraft-color = { path = "crates/color" }
|
||||||
@@ -80,20 +80,20 @@ zip = { version = "3", default-features = false, features = ["deflate"] }
|
|||||||
indd = { git = "https://github.com/storytold/indd-utils", branch = "main" }
|
indd = { git = "https://github.com/storytold/indd-utils", branch = "main" }
|
||||||
|
|
||||||
# Which paths stored in documents may be followed (craft-libs).
|
# Which paths stored in documents may be followed (craft-libs).
|
||||||
craft-docpath = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7" }
|
craft-docpath = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0" }
|
||||||
# Atomic file replacement for saves and exports (craft-libs).
|
# Atomic file replacement for saves and exports (craft-libs).
|
||||||
craft-atomic = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7" }
|
craft-atomic = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0" }
|
||||||
# File › Print through the system print spooler (craft-libs).
|
# File › Print through the system print spooler (craft-libs).
|
||||||
craft-print = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7" }
|
craft-print = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0" }
|
||||||
|
|
||||||
# ICC colour management: working spaces, transforms, black point compensation (craft-libs).
|
# ICC colour management: working spaces, transforms, black point compensation (craft-libs).
|
||||||
craft-cms = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7" }
|
craft-cms = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0" }
|
||||||
|
|
||||||
# ui
|
# ui
|
||||||
# Shared frontend components; keep this dependency above the engine boundary.
|
# Shared frontend components; keep this dependency above the engine boundary.
|
||||||
craft-ui = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7", features = ["serde"] }
|
craft-ui = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", features = ["serde"] }
|
||||||
# The application bar as the window's title bar (craft-libs).
|
# The application bar as the window's title bar (craft-libs).
|
||||||
craft-window = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7", features = ["egui"] }
|
craft-window = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", features = ["egui"] }
|
||||||
egui = "0.37"
|
egui = "0.37"
|
||||||
egui_extras = { version = "0.37", default-features = false, features = ["svg"] }
|
egui_extras = { version = "0.37", default-features = false, features = ["svg"] }
|
||||||
eframe = { version = "0.37", default-features = false }
|
eframe = { version = "0.37", default-features = false }
|
||||||
@@ -131,16 +131,16 @@ debug = 0
|
|||||||
|
|
||||||
# Opt-in cancelable macOS termination on the pinned winit 0.30 line.
|
# Opt-in cancelable macOS termination on the pinned winit 0.30 line.
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
krilla = { git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7", version = "=0.8.2" }
|
krilla = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.8.2" }
|
||||||
winit = { git = "https://github.com/storytold/winit.git", rev = "a517b3846ee8457d84ee4975110bfda6797c44dc" }
|
winit = { git = "https://github.com/storytold/winit.git", rev = "a517b3846ee8457d84ee4975110bfda6797c44dc" }
|
||||||
# The hayro crates from craft-libs' vendor/ directory (pdfcraft's, plus the plate mode and decode
|
# The hayro crates from craft-libs' vendor/ directory (pdfcraft's, plus the plate mode and decode
|
||||||
# limits craft-pdf and craft-prepress need); same revision as craft-pdf.
|
# limits craft-pdf and craft-prepress need); same revision as craft-pdf.
|
||||||
hayro = { git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7", version = "=0.7.1" }
|
hayro = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.7.1" }
|
||||||
hayro-interpret = { git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7", version = "=0.7.0" }
|
hayro-interpret = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.7.0" }
|
||||||
hayro-syntax = { git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7", version = "=0.7.2" }
|
hayro-syntax = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.7.2" }
|
||||||
hayro-jbig2 = { git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7", version = "=0.3.0" }
|
hayro-jbig2 = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.3.0" }
|
||||||
hayro-cmap = { git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7", version = "=0.1.0" }
|
hayro-cmap = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.1.0" }
|
||||||
hayro-postscript = { git = "https://github.com/storytold/craft-libs", rev = "b926b5c03e256c86ca10934f58d03f628810b5b7", version = "=0.1.0" }
|
hayro-postscript = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.1.0" }
|
||||||
ecolor = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
ecolor = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
||||||
emath = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
emath = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
||||||
epaint = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
epaint = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
|
||||||
|
|||||||
@@ -2,3 +2,6 @@ allow-unwrap-in-tests = true
|
|||||||
allow-expect-in-tests = true
|
allow-expect-in-tests = true
|
||||||
allow-panic-in-tests = true
|
allow-panic-in-tests = true
|
||||||
allow-indexing-slicing-in-tests = true
|
allow-indexing-slicing-in-tests = true
|
||||||
|
disallowed-types = [
|
||||||
|
{ path = "egui::ComboBox", reason = "use craft_ui::ComboBox: egui's combo box menu can't grow back while open (egui#5225)" },
|
||||||
|
]
|
||||||
@@ -38,7 +38,7 @@ fn page_preset_and_orientation(app: &mut DesignApp, ui: &mut egui::Ui, lang: &st
|
|||||||
let landscape = size.0 > size.1;
|
let landscape = size.0 > size.1;
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
let cur = panels::properties::preset_name(size.0, size.1);
|
let cur = panels::properties::preset_name(size.0, size.1);
|
||||||
egui::ComboBox::from_id_salt("ctl_page_preset").selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, cur))).width(130.0).show_ui(
|
craft_ui::ComboBox::from_id_salt("ctl_page_preset").selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, cur))).width(130.0).show_ui(
|
||||||
ui,
|
ui,
|
||||||
|ui| {
|
|ui| {
|
||||||
for (name, w, h) in panels::properties::PAGE_PRESETS {
|
for (name, w, h) in panels::properties::PAGE_PRESETS {
|
||||||
@@ -105,7 +105,7 @@ fn control_page(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
caption(ui, crate::i18n::tr(&lang, "Liquid Page Rule:"));
|
caption(ui, crate::i18n::tr(&lang, "Liquid Page Rule:"));
|
||||||
let label = panels::interactive::liquid_rule_label(pg.liquid);
|
let label = panels::interactive::liquid_rule_label(pg.liquid);
|
||||||
egui::ComboBox::from_id_salt("ctl_page_rule").selected_text(crate::rtl::widget(ui, crate::i18n::tr(&lang, label))).width(150.0).show_ui(
|
craft_ui::ComboBox::from_id_salt("ctl_page_rule").selected_text(crate::rtl::widget(ui, crate::i18n::tr(&lang, label))).width(150.0).show_ui(
|
||||||
ui,
|
ui,
|
||||||
|ui| {
|
|ui| {
|
||||||
for (r, l) in panels::interactive::LIQUID_RULES {
|
for (r, l) in panels::interactive::LIQUID_RULES {
|
||||||
@@ -368,7 +368,7 @@ fn control_character(
|
|||||||
let cs = attrs.as_ref().and_then(|a| a["characterStyle"].as_str()).unwrap_or(designcraft_doc::NO_CHAR_STYLE).to_string();
|
let cs = attrs.as_ref().and_then(|a| a["characterStyle"].as_str()).unwrap_or(designcraft_doc::NO_CHAR_STYLE).to_string();
|
||||||
let names: Vec<String> = app.session.active().map(|d| d.doc.styles.character.iter().map(|c| c.name.clone()).collect()).unwrap_or_default();
|
let names: Vec<String> = app.session.active().map(|d| d.doc.styles.character.iter().map(|c| c.name.clone()).collect()).unwrap_or_default();
|
||||||
let mut pick = None;
|
let mut pick = None;
|
||||||
egui::ComboBox::from_id_salt("ctl_char_style")
|
craft_ui::ComboBox::from_id_salt("ctl_char_style")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, &cs)))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, &cs)))
|
||||||
.width(150.0)
|
.width(150.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -382,7 +382,7 @@ fn control_character(
|
|||||||
let _ = app.run("style.character.apply", json!({"name": n}));
|
let _ = app.run("style.character.apply", json!({"name": n}));
|
||||||
}
|
}
|
||||||
let lang = chars["language"].as_str().unwrap_or("English: USA").to_string();
|
let lang = chars["language"].as_str().unwrap_or("English: USA").to_string();
|
||||||
egui::ComboBox::from_id_salt("ctl_language").selected_text(crate::rtl::widget(ui, tr(&lang))).width(150.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("ctl_language").selected_text(crate::rtl::widget(ui, tr(&lang))).width(150.0).show_ui(ui, |ui| {
|
||||||
egui::ScrollArea::vertical().max_height(320.0).show(ui, |ui| crate::panels::properties::language_menu(app, ui, &lang));
|
egui::ScrollArea::vertical().max_height(320.0).show(ui, |ui| crate::panels::properties::language_menu(app, ui, &lang));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ fn controls(ui: &mut egui::Ui, v: &mut View, lang: &str) {
|
|||||||
}
|
}
|
||||||
ui.separator();
|
ui.separator();
|
||||||
ui.label(tr(lang, "Sort"));
|
ui.label(tr(lang, "Sort"));
|
||||||
egui::ComboBox::from_id_salt("credits_sort").selected_text(tr(lang, v.key.label().0)).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("credits_sort").selected_text(tr(lang, v.key.label().0)).show_ui(ui, |ui| {
|
||||||
for k in SortKey::ALL {
|
for k in SortKey::ALL {
|
||||||
if ui.selectable_label(v.key == k, tr(lang, k.label().0)).clicked() {
|
if ui.selectable_label(v.key == k, tr(lang, k.label().0)).clicked() {
|
||||||
v.key = k;
|
v.key = k;
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ fn epub_export(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
|||||||
d.fields.insert("mode".into(), json!("style"));
|
d.fields.insert("mode".into(), json!("style"));
|
||||||
}
|
}
|
||||||
let cur = d.s("style");
|
let cur = d.s("style");
|
||||||
egui::ComboBox::from_id_salt("epub_split_style").selected_text(crate::rtl::widget(ui, &cur)).width(180.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("epub_split_style").selected_text(crate::rtl::widget(ui, &cur)).width(180.0).show_ui(ui, |ui| {
|
||||||
for name in &styles {
|
for name in &styles {
|
||||||
if ui.selectable_label(cur == *name, crate::rtl::widget(ui, name)).clicked() {
|
if ui.selectable_label(cur == *name, crate::rtl::widget(ui, name)).clicked() {
|
||||||
d.fields.insert("style".into(), json!(name));
|
d.fields.insert("style".into(), json!(name));
|
||||||
@@ -343,7 +343,7 @@ fn print_dialog(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
|||||||
if printers.is_empty() {
|
if printers.is_empty() {
|
||||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "System default")).italics());
|
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "System default")).italics());
|
||||||
} else {
|
} else {
|
||||||
egui::ComboBox::from_id_salt("printer").selected_text(&cur).width(220.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("printer").selected_text(&cur).width(220.0).show_ui(ui, |ui| {
|
||||||
for p in &printers {
|
for p in &printers {
|
||||||
if ui.selectable_label(*p == cur, p).clicked() {
|
if ui.selectable_label(*p == cur, p).clicked() {
|
||||||
d.fields.insert("printer".into(), json!(p));
|
d.fields.insert("printer".into(), json!(p));
|
||||||
@@ -423,7 +423,7 @@ fn pdf_export(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
|||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
crate::rtl::label(ui, crate::i18n::tr(lang, "Preset:"));
|
crate::rtl::label(ui, crate::i18n::tr(lang, "Preset:"));
|
||||||
let cur = d.s("preset");
|
let cur = d.s("preset");
|
||||||
egui::ComboBox::from_id_salt("pdf_preset").selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, &cur))).width(200.0).show_ui(
|
craft_ui::ComboBox::from_id_salt("pdf_preset").selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, &cur))).width(200.0).show_ui(
|
||||||
ui,
|
ui,
|
||||||
|ui| {
|
|ui| {
|
||||||
for p in PDF_EXPORT_PRESETS {
|
for p in PDF_EXPORT_PRESETS {
|
||||||
@@ -1508,7 +1508,7 @@ fn document_setup(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) ->
|
|||||||
setup_row(ui, rtl, |ui| {
|
setup_row(ui, rtl, |ui| {
|
||||||
setup_caption(ui, tr("Intent:"), label_w);
|
setup_caption(ui, tr("Intent:"), label_w);
|
||||||
let cur = d.s("intent");
|
let cur = d.s("intent");
|
||||||
egui::ComboBox::from_id_salt("ds_intent")
|
craft_ui::ComboBox::from_id_salt("ds_intent")
|
||||||
.selected_text(crate::rtl::widget(
|
.selected_text(crate::rtl::widget(
|
||||||
ui,
|
ui,
|
||||||
tr(match cur.as_str() {
|
tr(match cur.as_str() {
|
||||||
@@ -1542,7 +1542,7 @@ fn document_setup(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) ->
|
|||||||
setup_row(ui, rtl, |ui| {
|
setup_row(ui, rtl, |ui| {
|
||||||
setup_caption(ui, tr("Binding:"), label_w);
|
setup_caption(ui, tr("Binding:"), label_w);
|
||||||
let right_to_left = d.s("binding") == "rightToLeft";
|
let right_to_left = d.s("binding") == "rightToLeft";
|
||||||
egui::ComboBox::from_id_salt("ds_binding")
|
craft_ui::ComboBox::from_id_salt("ds_binding")
|
||||||
.selected_text(crate::rtl::widget(ui, tr(if right_to_left { "Right to Left" } else { "Left to Right" })))
|
.selected_text(crate::rtl::widget(ui, tr(if right_to_left { "Right to Left" } else { "Left to Right" })))
|
||||||
.width(150.0)
|
.width(150.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -1563,7 +1563,7 @@ fn document_setup(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog) ->
|
|||||||
setup_group(ui, |ui| {
|
setup_group(ui, |ui| {
|
||||||
setup_row(ui, rtl, |ui| {
|
setup_row(ui, rtl, |ui| {
|
||||||
crate::rtl::label(ui, egui::RichText::new(tr("Page Size:")).color(t.text_strong));
|
crate::rtl::label(ui, egui::RichText::new(tr("Page Size:")).color(t.text_strong));
|
||||||
egui::ComboBox::from_id_salt("ds_preset").selected_text(crate::rtl::widget(ui, &preset)).width(260.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("ds_preset").selected_text(crate::rtl::widget(ui, &preset)).width(260.0).show_ui(ui, |ui| {
|
||||||
for p in designcraft_doc::build::PRESETS {
|
for p in designcraft_doc::build::PRESETS {
|
||||||
if ui.selectable_label(tr(p.name) == preset, crate::rtl::widget(ui, tr(p.name))).clicked() {
|
if ui.selectable_label(tr(p.name) == preset, crate::rtl::widget(ui, tr(p.name))).clicked() {
|
||||||
// Keep the orientation; the preset's size in the document's units.
|
// Keep the orientation; the preset's size in the document's units.
|
||||||
@@ -1915,7 +1915,7 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog, max_he
|
|||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "On Screen:"));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "On Screen:"));
|
||||||
let rich = d.b("richBlack");
|
let rich = d.b("richBlack");
|
||||||
egui::ComboBox::from_id_salt("pref_black")
|
craft_ui::ComboBox::from_id_salt("pref_black")
|
||||||
.selected_text(crate::rtl::widget(
|
.selected_text(crate::rtl::widget(
|
||||||
ui,
|
ui,
|
||||||
crate::i18n::tr(
|
crate::i18n::tr(
|
||||||
@@ -1935,7 +1935,7 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog, max_he
|
|||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Printing / Exporting:"));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Printing / Exporting:"));
|
||||||
let rich = d.b("richBlackOutput");
|
let rich = d.b("richBlackOutput");
|
||||||
egui::ComboBox::from_id_salt("pref_black_out")
|
craft_ui::ComboBox::from_id_salt("pref_black_out")
|
||||||
.selected_text(crate::rtl::widget(
|
.selected_text(crate::rtl::widget(
|
||||||
ui,
|
ui,
|
||||||
crate::i18n::tr(
|
crate::i18n::tr(
|
||||||
@@ -1985,7 +1985,7 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog, max_he
|
|||||||
ui.end_row();
|
ui.end_row();
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Relative To:"));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Relative To:"));
|
||||||
let cur = d.s("bg.relativeTo");
|
let cur = d.s("bg.relativeTo");
|
||||||
egui::ComboBox::from_id_salt("bg_rel")
|
craft_ui::ComboBox::from_id_salt("bg_rel")
|
||||||
.selected_text(crate::rtl::widget(
|
.selected_text(crate::rtl::widget(
|
||||||
ui,
|
ui,
|
||||||
crate::i18n::tr(&app.ui.language, if cur == "topMargin" { "Top Margin" } else { "Top of Page" }),
|
crate::i18n::tr(&app.ui.language, if cur == "topMargin" { "Top Margin" } else { "Top of Page" }),
|
||||||
@@ -2066,7 +2066,7 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog, max_he
|
|||||||
let cur = d.s("displayQuality");
|
let cur = d.s("displayQuality");
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Default View:"));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Default View:"));
|
||||||
egui::ComboBox::from_id_salt("pref_dq")
|
craft_ui::ComboBox::from_id_salt("pref_dq")
|
||||||
.selected_text(match cur.as_str() {
|
.selected_text(match cur.as_str() {
|
||||||
"fast" => crate::i18n::tr(&app.ui.language, "Fast"),
|
"fast" => crate::i18n::tr(&app.ui.language, "Fast"),
|
||||||
"typical" => crate::i18n::tr(&app.ui.language, "Typical"),
|
"typical" => crate::i18n::tr(&app.ui.language, "Typical"),
|
||||||
@@ -2088,7 +2088,7 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog, max_he
|
|||||||
let cur = d.fields.get("rulerOrigin").and_then(Value::as_str).unwrap_or("spread").to_string();
|
let cur = d.fields.get("rulerOrigin").and_then(Value::as_str).unwrap_or("spread").to_string();
|
||||||
const ORIGINS: [(&str, &str); 3] = [("spread", "Spread"), ("page", "Page"), ("spine", "Spine")];
|
const ORIGINS: [(&str, &str); 3] = [("spread", "Spread"), ("page", "Page"), ("spine", "Spine")];
|
||||||
let shown = ORIGINS.iter().find(|o| o.0 == cur).map_or("Spread", |o| o.1);
|
let shown = ORIGINS.iter().find(|o| o.0 == cur).map_or("Spread", |o| o.1);
|
||||||
egui::ComboBox::from_id_salt("rulerOrigin")
|
craft_ui::ComboBox::from_id_salt("rulerOrigin")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, shown)))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, shown)))
|
||||||
.width(140.0)
|
.width(140.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -2102,7 +2102,7 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog, max_he
|
|||||||
for (key, label) in [("horizontalUnits", "Horizontal:"), ("verticalUnits", "Vertical:")] {
|
for (key, label) in [("horizontalUnits", "Horizontal:"), ("verticalUnits", "Vertical:")] {
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label));
|
||||||
let cur: Unit = d.fields.get(key).and_then(|v| serde_json::from_value(v.clone()).ok()).unwrap_or_default();
|
let cur: Unit = d.fields.get(key).and_then(|v| serde_json::from_value(v.clone()).ok()).unwrap_or_default();
|
||||||
egui::ComboBox::from_id_salt(key)
|
craft_ui::ComboBox::from_id_salt(key)
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, cur.label())))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, cur.label())))
|
||||||
.width(140.0)
|
.width(140.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -2137,17 +2137,18 @@ fn preferences(app: &crate::DesignApp, ui: &mut egui::Ui, d: &mut Dialog, max_he
|
|||||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Interface Language")).font(semibold(12.0)));
|
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "Interface Language")).font(semibold(12.0)));
|
||||||
// Each language by its own name, so the list reads the same in every interface language.
|
// Each language by its own name, so the list reads the same in every interface language.
|
||||||
let current = crate::i18n::LANGUAGES.iter().find(|(code, _)| *code == app.ui.language).map_or("English", |(_, name)| *name);
|
let current = crate::i18n::LANGUAGES.iter().find(|(code, _)| *code == app.ui.language).map_or("English", |(_, name)| *name);
|
||||||
egui::ComboBox::from_id_salt("pref_language").width(180.0).height(400.0).selected_text(crate::rtl::widget(ui, current)).show_ui(
|
craft_ui::ComboBox::from_id_salt("pref_language")
|
||||||
ui,
|
.width(180.0)
|
||||||
|ui| {
|
.height(400.0)
|
||||||
|
.selected_text(crate::rtl::widget(ui, current))
|
||||||
|
.show_ui(ui, |ui| {
|
||||||
for (code, name) in crate::i18n::picker_languages() {
|
for (code, name) in crate::i18n::picker_languages() {
|
||||||
if ui.selectable_label(code == app.ui.language, crate::rtl::widget(ui, name)).clicked() {
|
if ui.selectable_label(code == app.ui.language, crate::rtl::widget(ui, name)).clicked() {
|
||||||
// Applied by `show` right after this frame, which has `&mut DesignApp`.
|
// Applied by `show` right after this frame, which has `&mut DesignApp`.
|
||||||
d.fields.insert("applyLanguage".into(), json!(code));
|
d.fields.insert("applyLanguage".into(), json!(code));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "When Scaling")).font(semibold(12.0)));
|
crate::rtl::label(ui, egui::RichText::new(crate::i18n::tr(&app.ui.language, "When Scaling")).font(semibold(12.0)));
|
||||||
check(ui, d, "scaleStrokes", crate::i18n::tr(&app.ui.language, "Include Stroke Weight"));
|
check(ui, d, "scaleStrokes", crate::i18n::tr(&app.ui.language, "Include Stroke Weight"));
|
||||||
@@ -2392,7 +2393,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
|||||||
for (key, label, any) in [("objFill", "Find fill:", "(any)"), ("objChangeFill", "Change fill to:", "(unchanged)")] {
|
for (key, label, any) in [("objFill", "Find fill:", "(any)"), ("objChangeFill", "Change fill to:", "(unchanged)")] {
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label));
|
||||||
let cur = d.s(key);
|
let cur = d.s(key);
|
||||||
egui::ComboBox::from_id_salt(key)
|
craft_ui::ComboBox::from_id_salt(key)
|
||||||
.selected_text(if cur.is_empty() { crate::i18n::tr(&app.ui.language, any) } else { cur.as_str() })
|
.selected_text(if cur.is_empty() { crate::i18n::tr(&app.ui.language, any) } else { cur.as_str() })
|
||||||
.width(180.0)
|
.width(180.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -2412,7 +2413,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
|||||||
}
|
}
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Kind:"));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Kind:"));
|
||||||
let cur = d.s("objKind");
|
let cur = d.s("objKind");
|
||||||
egui::ComboBox::from_id_salt("objKind")
|
craft_ui::ComboBox::from_id_salt("objKind")
|
||||||
.selected_text(if cur.is_empty() { crate::i18n::tr(&app.ui.language, "(any)") } else { cur.as_str() })
|
.selected_text(if cur.is_empty() { crate::i18n::tr(&app.ui.language, "(any)") } else { cur.as_str() })
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
for v in ["", "text", "graphic", "shape", "line", "group"] {
|
for v in ["", "text", "graphic", "shape", "line", "group"] {
|
||||||
@@ -2461,7 +2462,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
|||||||
ui.end_row();
|
ui.end_row();
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Search:"));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Search:"));
|
||||||
let cur = d.s("scope");
|
let cur = d.s("scope");
|
||||||
egui::ComboBox::from_id_salt("fcscope")
|
craft_ui::ComboBox::from_id_salt("fcscope")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, &cur)))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, &cur)))
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
for v in ["document", "story", "selection"] {
|
for v in ["document", "story", "selection"] {
|
||||||
@@ -2571,7 +2572,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
|||||||
"media" => crate::i18n::tr(&app.ui.language, "Media"),
|
"media" => crate::i18n::tr(&app.ui.language, "Media"),
|
||||||
_ => crate::i18n::tr(&app.ui.language, "Crop"),
|
_ => crate::i18n::tr(&app.ui.language, "Crop"),
|
||||||
};
|
};
|
||||||
egui::ComboBox::from_id_salt("pdf_crop").selected_text(crate::rtl::widget(ui, label(&cur))).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("pdf_crop").selected_text(crate::rtl::widget(ui, label(&cur))).show_ui(ui, |ui| {
|
||||||
for v in designcraft_doc::PdfCrop::ALL.map(designcraft_doc::PdfCrop::name) {
|
for v in designcraft_doc::PdfCrop::ALL.map(designcraft_doc::PdfCrop::name) {
|
||||||
if ui.selectable_label(label(&cur) == label(v), label(v)).clicked() {
|
if ui.selectable_label(label(&cur) == label(v), label(v)).clicked() {
|
||||||
d.fields.insert("crop".into(), json!(v));
|
d.fields.insert("crop".into(), json!(v));
|
||||||
@@ -2608,7 +2609,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
|||||||
for (key, label, kind) in [("rgb", "RGB:", "rgb"), ("cmyk", "CMYK:", "cmyk")] {
|
for (key, label, kind) in [("rgb", "RGB:", "rgb"), ("cmyk", "CMYK:", "cmyk")] {
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, label));
|
||||||
let cur = d.s(key);
|
let cur = d.s(key);
|
||||||
egui::ComboBox::from_id_salt(("ws", key)).selected_text(&cur).width(260.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt(("ws", key)).selected_text(&cur).width(260.0).show_ui(ui, |ui| {
|
||||||
for pr in profiles.iter().filter(|p| p["kind"] == kind) {
|
for pr in profiles.iter().filter(|p| p["kind"] == kind) {
|
||||||
let name = pr["name"].as_str().unwrap_or("");
|
let name = pr["name"].as_str().unwrap_or("");
|
||||||
if ui.selectable_label(name == cur, name).clicked() {
|
if ui.selectable_label(name == cur, name).clicked() {
|
||||||
@@ -2620,7 +2621,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
|||||||
}
|
}
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Intent:"));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Intent:"));
|
||||||
let cur = d.s("intent");
|
let cur = d.s("intent");
|
||||||
egui::ComboBox::from_id_salt("ws_intent")
|
craft_ui::ComboBox::from_id_salt("ws_intent")
|
||||||
.selected_text(crate::rtl::widget(
|
.selected_text(crate::rtl::widget(
|
||||||
ui,
|
ui,
|
||||||
crate::i18n::tr(&app.ui.language, designcraft_color::cms::Intent::parse(&cur).map_or("", |i| i.label())),
|
crate::i18n::tr(&app.ui.language, designcraft_color::cms::Intent::parse(&cur).map_or("", |i| i.label())),
|
||||||
@@ -2731,7 +2732,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
|||||||
} else {
|
} else {
|
||||||
mapped.clone()
|
mapped.clone()
|
||||||
};
|
};
|
||||||
egui::ComboBox::from_id_salt(("imp_map", w))
|
craft_ui::ComboBox::from_id_salt(("imp_map", w))
|
||||||
.selected_text(crate::rtl::widget(ui, &shown))
|
.selected_text(crate::rtl::widget(ui, &shown))
|
||||||
.width(170.0)
|
.width(170.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -2852,7 +2853,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
|||||||
};
|
};
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Fitting:"));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Fitting:"));
|
||||||
egui::ComboBox::from_id_salt("ff_fit").selected_text(crate::rtl::widget(ui, label(&cur))).width(200.0).show_ui(
|
craft_ui::ComboBox::from_id_salt("ff_fit").selected_text(crate::rtl::widget(ui, label(&cur))).width(200.0).show_ui(
|
||||||
ui,
|
ui,
|
||||||
|ui| {
|
|ui| {
|
||||||
for v in ["none", "fillProportionally", "fitProportionally", "fitContentToFrame", "centerContent"] {
|
for v in ["none", "fillProportionally", "fitProportionally", "fitContentToFrame", "centerContent"] {
|
||||||
@@ -2910,7 +2911,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
|||||||
"vcard" => crate::i18n::tr(&app.ui.language, "Business Card"),
|
"vcard" => crate::i18n::tr(&app.ui.language, "Business Card"),
|
||||||
_ => crate::i18n::tr(&app.ui.language, "Web Hyperlink"),
|
_ => crate::i18n::tr(&app.ui.language, "Web Hyperlink"),
|
||||||
};
|
};
|
||||||
egui::ComboBox::from_id_salt("qr_type").selected_text(crate::rtl::widget(ui, label(&cur))).width(160.0).show_ui(
|
craft_ui::ComboBox::from_id_salt("qr_type").selected_text(crate::rtl::widget(ui, label(&cur))).width(160.0).show_ui(
|
||||||
ui,
|
ui,
|
||||||
|ui| {
|
|ui| {
|
||||||
for v in ["url", "text", "sms", "email", "vcard"] {
|
for v in ["url", "text", "sms", "email", "vcard"] {
|
||||||
@@ -4143,7 +4144,7 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
|||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Tag:"));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Tag:"));
|
||||||
let cur = d.s("x.tag");
|
let cur = d.s("x.tag");
|
||||||
egui::ComboBox::from_id_salt("export_tag")
|
craft_ui::ComboBox::from_id_salt("export_tag")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, &cur)))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, &cur)))
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
for t in ["[Automatic]", "p", "h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "pre", "li", "figcaption", "aside", "div"]
|
for t in ["[Automatic]", "p", "h1", "h2", "h3", "h4", "h5", "h6", "blockquote", "pre", "li", "figcaption", "aside", "div"]
|
||||||
@@ -4167,7 +4168,7 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
|||||||
egui::Grid::new("psi").num_columns(2).spacing([8.0, 6.0]).show(ui, |ui| {
|
egui::Grid::new("psi").num_columns(2).spacing([8.0, 6.0]).show(ui, |ui| {
|
||||||
let alignment_label = crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Alignment:"));
|
let alignment_label = crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Alignment:"));
|
||||||
let a: designcraft_doc::Align = serde_json::from_value(cur(d, "p.align", &pv["align"])).unwrap_or_default();
|
let a: designcraft_doc::Align = serde_json::from_value(cur(d, "p.align", &pv["align"])).unwrap_or_default();
|
||||||
egui::ComboBox::from_id_salt("psalign")
|
craft_ui::ComboBox::from_id_salt("psalign")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, a.label())))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, a.label())))
|
||||||
.width(240.0)
|
.width(240.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -4201,7 +4202,7 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
|||||||
let grid_label = crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Align to Grid:"));
|
let grid_label = crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Align to Grid:"));
|
||||||
let g: GridAlign = serde_json::from_value(cur(d, "p.gridAlign", &pv["gridAlign"])).unwrap_or_default();
|
let g: GridAlign = serde_json::from_value(cur(d, "p.gridAlign", &pv["gridAlign"])).unwrap_or_default();
|
||||||
let shown = GRID_ALIGN.iter().find(|o| o.0 == g).map_or("", |o| o.1);
|
let shown = GRID_ALIGN.iter().find(|o| o.0 == g).map_or("", |o| o.1);
|
||||||
egui::ComboBox::from_id_salt("psgridalign")
|
craft_ui::ComboBox::from_id_salt("psgridalign")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, shown)))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, shown)))
|
||||||
.width(240.0)
|
.width(240.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -4265,7 +4266,7 @@ fn paragraph_style_options(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
|||||||
.map(str::to_string)
|
.map(str::to_string)
|
||||||
.or(style.based_on.clone())
|
.or(style.based_on.clone())
|
||||||
.unwrap_or_else(|| "[No Paragraph Style]".into());
|
.unwrap_or_else(|| "[No Paragraph Style]".into());
|
||||||
let combo = egui::ComboBox::from_id_salt("psbased")
|
let combo = craft_ui::ComboBox::from_id_salt("psbased")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, &based)))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, &based)))
|
||||||
.width(220.0)
|
.width(220.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -4372,7 +4373,7 @@ fn delete_paragraph_style(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog
|
|||||||
d.fields.insert("replaceWith".into(), json!(designcraft_doc::BASIC_PARAGRAPH));
|
d.fields.insert("replaceWith".into(), json!(designcraft_doc::BASIC_PARAGRAPH));
|
||||||
}
|
}
|
||||||
let replace = d.s("replaceWith");
|
let replace = d.s("replaceWith");
|
||||||
egui::ComboBox::from_id_salt("del_para_replace")
|
craft_ui::ComboBox::from_id_salt("del_para_replace")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, &replace)))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, &replace)))
|
||||||
.width(260.0)
|
.width(260.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -4506,7 +4507,7 @@ fn para_measure(ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, key: &str, unit:
|
|||||||
fn para_choice(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, key: &str, opts: &[(&str, &str)]) {
|
fn para_choice(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, key: &str, opts: &[(&str, &str)]) {
|
||||||
let cur = para_value(d, pv, key);
|
let cur = para_value(d, pv, key);
|
||||||
let shown = opts.iter().find(|o| cur == o.0).map_or("", |o| crate::i18n::tr(lang, o.1));
|
let shown = opts.iter().find(|o| cur == o.0).map_or("", |o| crate::i18n::tr(lang, o.1));
|
||||||
egui::ComboBox::from_id_salt(("pschoice", key)).selected_text(crate::rtl::widget(ui, shown)).width(200.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt(("pschoice", key)).selected_text(crate::rtl::widget(ui, shown)).width(200.0).show_ui(ui, |ui| {
|
||||||
for (v, label) in opts {
|
for (v, label) in opts {
|
||||||
if ui.selectable_label(cur == *v, crate::rtl::widget(ui, crate::i18n::tr(lang, label))).clicked() {
|
if ui.selectable_label(cur == *v, crate::rtl::widget(ui, crate::i18n::tr(lang, label))).clicked() {
|
||||||
para_set(d, key, json!(v));
|
para_set(d, key, json!(v));
|
||||||
@@ -4543,7 +4544,7 @@ fn para_sides(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, key: &s
|
|||||||
/// picked.
|
/// picked.
|
||||||
fn swatch_menu(ui: &mut egui::Ui, doc: &designcraft_doc::Document, id: impl egui::AsIdSalt, current: &str, width: f32) -> Option<String> {
|
fn swatch_menu(ui: &mut egui::Ui, doc: &designcraft_doc::Document, id: impl egui::AsIdSalt, current: &str, width: f32) -> Option<String> {
|
||||||
let mut picked = None;
|
let mut picked = None;
|
||||||
egui::ComboBox::from_id_salt(id).selected_text(current).width(width).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt(id).selected_text(current).width(width).show_ui(ui, |ui| {
|
||||||
for w in doc.swatches.iter().filter(|w| !w.hidden) {
|
for w in doc.swatches.iter().filter(|w| !w.hidden) {
|
||||||
let (c, g) = crate::widgets::swatch_colors(doc, &w.name, 1.0);
|
let (c, g) = crate::widgets::swatch_colors(doc, &w.name, 1.0);
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
@@ -4570,7 +4571,7 @@ fn border_type_menu(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, d
|
|||||||
StrokeType::Style { name } => name.clone(),
|
StrokeType::Style { name } => name.clone(),
|
||||||
k => crate::i18n::tr(lang, k.label()).to_string(),
|
k => crate::i18n::tr(lang, k.label()).to_string(),
|
||||||
};
|
};
|
||||||
egui::ComboBox::from_id_salt("psbordertype").selected_text(crate::rtl::widget(ui, shown)).width(160.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("psbordertype").selected_text(crate::rtl::widget(ui, shown)).width(160.0).show_ui(ui, |ui| {
|
||||||
for k in BORDER_TYPES {
|
for k in BORDER_TYPES {
|
||||||
let ty = if k == "dashed" { json!({"kind": k, "pattern": []}) } else { json!({"kind": k}) };
|
let ty = if k == "dashed" { json!({"kind": k, "pattern": []}) } else { json!({"kind": k}) };
|
||||||
let Ok(t) = serde_json::from_value::<StrokeType>(ty.clone()) else { continue };
|
let Ok(t) = serde_json::from_value::<StrokeType>(ty.clone()) else { continue };
|
||||||
@@ -4602,7 +4603,7 @@ fn para_corners(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, key:
|
|||||||
c.size = if v.is_finite() { v.clamp(0.0, 10_000.0) } else { 0.0 };
|
c.size = if v.is_finite() { v.clamp(0.0, 10_000.0) } else { 0.0 };
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
egui::ComboBox::from_id_salt(("pscornershape", key, i))
|
craft_ui::ComboBox::from_id_salt(("pscornershape", key, i))
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, c.shape.label())))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, c.shape.label())))
|
||||||
.width(130.0)
|
.width(130.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -4761,7 +4762,7 @@ fn drop_cap_fields(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, cn
|
|||||||
crate::rtl::label(ui, crate::i18n::tr(lang, "Character Style:"));
|
crate::rtl::label(ui, crate::i18n::tr(lang, "Character Style:"));
|
||||||
let style = field_or(d, "p.dropCapStyle", &pv["dropCapStyle"]).as_str().unwrap_or("").to_string();
|
let style = field_or(d, "p.dropCapStyle", &pv["dropCapStyle"]).as_str().unwrap_or("").to_string();
|
||||||
let style = if style.is_empty() { designcraft_doc::NO_CHAR_STYLE.to_string() } else { style };
|
let style = if style.is_empty() { designcraft_doc::NO_CHAR_STYLE.to_string() } else { style };
|
||||||
egui::ComboBox::from_id_salt("ps_dropcap_style")
|
craft_ui::ComboBox::from_id_salt("ps_dropcap_style")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(lang, &style)))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(lang, &style)))
|
||||||
.width(160.0)
|
.width(160.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -4812,19 +4813,19 @@ fn nested_style_rows(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value,
|
|||||||
fn nested_style_row(lang: &str, ui: &mut egui::Ui, ns: &mut Value, i: usize, cnames: &[String]) -> (bool, bool) {
|
fn nested_style_row(lang: &str, ui: &mut egui::Ui, ns: &mut Value, i: usize, cnames: &[String]) -> (bool, bool) {
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
let style = ns["style"].as_str().unwrap_or("[None]").to_string();
|
let style = ns["style"].as_str().unwrap_or("[None]").to_string();
|
||||||
egui::ComboBox::from_id_salt(("ns_style", i)).selected_text(crate::rtl::widget(ui, crate::i18n::style_name(lang, &style))).width(110.0).show_ui(
|
craft_ui::ComboBox::from_id_salt(("ns_style", i))
|
||||||
ui,
|
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(lang, &style)))
|
||||||
|ui| {
|
.width(110.0)
|
||||||
|
.show_ui(ui, |ui| {
|
||||||
for c in cnames {
|
for c in cnames {
|
||||||
if ui.selectable_label(*c == style, crate::rtl::widget(ui, crate::i18n::style_name(lang, c))).clicked() {
|
if ui.selectable_label(*c == style, crate::rtl::widget(ui, crate::i18n::style_name(lang, c))).clicked() {
|
||||||
ns["style"] = json!(c);
|
ns["style"] = json!(c);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
let through = ns["through"].as_bool().unwrap_or(true);
|
let through = ns["through"].as_bool().unwrap_or(true);
|
||||||
egui::ComboBox::from_id_salt(("ns_thr", i))
|
craft_ui::ComboBox::from_id_salt(("ns_thr", i))
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, if through { "through" } else { "up to" })))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, if through { "through" } else { "up to" })))
|
||||||
.width(70.0)
|
.width(70.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -4846,7 +4847,7 @@ fn nested_style_row(lang: &str, ui: &mut egui::Ui, ns: &mut Value, i: usize, cna
|
|||||||
count_value(ui, ns, &mut changed);
|
count_value(ui, ns, &mut changed);
|
||||||
}
|
}
|
||||||
let kind = ns["until"]["kind"].as_str().unwrap_or("words").to_string();
|
let kind = ns["until"]["kind"].as_str().unwrap_or("words").to_string();
|
||||||
egui::ComboBox::from_id_salt(("ns_until", i))
|
craft_ui::ComboBox::from_id_salt(("ns_until", i))
|
||||||
.selected_text(crate::rtl::widget(
|
.selected_text(crate::rtl::widget(
|
||||||
ui,
|
ui,
|
||||||
if crate::i18n::category_first(lang) { format!("{}:", crate::i18n::tr(lang, &kind)) } else { crate::i18n::tr(lang, &kind).to_owned() },
|
if crate::i18n::category_first(lang) { format!("{}:", crate::i18n::tr(lang, &kind)) } else { crate::i18n::tr(lang, &kind).to_owned() },
|
||||||
@@ -4910,17 +4911,17 @@ fn nested_line_style_rows(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Va
|
|||||||
fn nested_line_style_row(lang: &str, ui: &mut egui::Ui, l: &mut Value, i: usize, cnames: &[String]) -> (bool, bool) {
|
fn nested_line_style_row(lang: &str, ui: &mut egui::Ui, l: &mut Value, i: usize, cnames: &[String]) -> (bool, bool) {
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
let style = l["style"].as_str().unwrap_or("").to_string();
|
let style = l["style"].as_str().unwrap_or("").to_string();
|
||||||
egui::ComboBox::from_id_salt(("nls_style", i)).selected_text(crate::rtl::widget(ui, crate::i18n::style_name(lang, &style))).width(130.0).show_ui(
|
craft_ui::ComboBox::from_id_salt(("nls_style", i))
|
||||||
ui,
|
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(lang, &style)))
|
||||||
|ui| {
|
.width(130.0)
|
||||||
|
.show_ui(ui, |ui| {
|
||||||
for c in cnames {
|
for c in cnames {
|
||||||
if ui.selectable_label(*c == style, crate::rtl::widget(ui, crate::i18n::style_name(lang, c))).clicked() {
|
if ui.selectable_label(*c == style, crate::rtl::widget(ui, crate::i18n::style_name(lang, c))).clicked() {
|
||||||
l["style"] = json!(c);
|
l["style"] = json!(c);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
crate::rtl::label(
|
crate::rtl::label(
|
||||||
ui,
|
ui,
|
||||||
if crate::i18n::category_first(lang) { format!("{}:", crate::i18n::tr(lang, "lines")) } else { crate::i18n::tr(lang, "for").to_owned() },
|
if crate::i18n::category_first(lang) { format!("{}:", crate::i18n::tr(lang, "lines")) } else { crate::i18n::tr(lang, "for").to_owned() },
|
||||||
@@ -4953,7 +4954,7 @@ fn grep_styles(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, cnames
|
|||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
crate::rtl::label(ui, crate::i18n::tr(lang, "Apply Style:"));
|
crate::rtl::label(ui, crate::i18n::tr(lang, "Apply Style:"));
|
||||||
let style = g["style"].as_str().unwrap_or("").to_string();
|
let style = g["style"].as_str().unwrap_or("").to_string();
|
||||||
egui::ComboBox::from_id_salt(("gs_style", i))
|
craft_ui::ComboBox::from_id_salt(("gs_style", i))
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(lang, &style)))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(lang, &style)))
|
||||||
.width(110.0)
|
.width(110.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -5068,7 +5069,7 @@ fn span_columns(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, doc:
|
|||||||
// "Span Columns" names both the section and this option, which some languages word differently.
|
// "Span Columns" names both the section and this option, which some languages word differently.
|
||||||
let kind_label = |k: &'static str| -> &'static str { crate::i18n::tr_context(lang, k, "paragraphLayout") };
|
let kind_label = |k: &'static str| -> &'static str { crate::i18n::tr_context(lang, k, "paragraphLayout") };
|
||||||
let shown = kinds.iter().find(|k| same(&k.1, &cur)).map_or("", |k| kind_label(k.0));
|
let shown = kinds.iter().find(|k| same(&k.1, &cur)).map_or("", |k| kind_label(k.0));
|
||||||
egui::ComboBox::from_id_salt("psspankind").selected_text(crate::rtl::widget(ui, shown)).width(200.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("psspankind").selected_text(crate::rtl::widget(ui, shown)).width(200.0).show_ui(ui, |ui| {
|
||||||
for (label, v) in kinds {
|
for (label, v) in kinds {
|
||||||
if ui.selectable_label(same(&v, &cur), crate::rtl::widget(ui, kind_label(label))).clicked() && !same(&v, &cur) {
|
if ui.selectable_label(same(&v, &cur), crate::rtl::widget(ui, kind_label(label))).clicked() && !same(&v, &cur) {
|
||||||
next = Some(v);
|
next = Some(v);
|
||||||
@@ -5081,7 +5082,7 @@ fn span_columns(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, doc:
|
|||||||
SpanColumns::Span(n) => {
|
SpanColumns::Span(n) => {
|
||||||
crate::rtl::label(ui, crate::i18n::tr(lang, "Columns:"));
|
crate::rtl::label(ui, crate::i18n::tr(lang, "Columns:"));
|
||||||
let shown = if n == 0 { crate::i18n::tr(lang, "All").to_string() } else { n.to_string() };
|
let shown = if n == 0 { crate::i18n::tr(lang, "All").to_string() } else { n.to_string() };
|
||||||
egui::ComboBox::from_id_salt("psspann").selected_text(crate::rtl::widget(ui, shown)).width(80.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("psspann").selected_text(crate::rtl::widget(ui, shown)).width(80.0).show_ui(ui, |ui| {
|
||||||
if ui.selectable_label(n == 0, crate::rtl::widget(ui, crate::i18n::tr(lang, "All"))).clicked() {
|
if ui.selectable_label(n == 0, crate::rtl::widget(ui, crate::i18n::tr(lang, "All"))).clicked() {
|
||||||
next = Some(SpanColumns::Span(0));
|
next = Some(SpanColumns::Span(0));
|
||||||
}
|
}
|
||||||
@@ -5174,9 +5175,10 @@ impl ListUi<'_> {
|
|||||||
/// A character style for a bullet or number (`key`), [None] first.
|
/// A character style for a bullet or number (`key`), [None] first.
|
||||||
fn list_char_style(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, key: &str, styles: &[String]) {
|
fn list_char_style(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, key: &str, styles: &[String]) {
|
||||||
let cur = para_value(d, pv, key).as_str().unwrap_or(designcraft_doc::NO_CHAR_STYLE).to_string();
|
let cur = para_value(d, pv, key).as_str().unwrap_or(designcraft_doc::NO_CHAR_STYLE).to_string();
|
||||||
egui::ComboBox::from_id_salt(("pslistcs", key)).selected_text(crate::rtl::widget(ui, crate::i18n::style_name(lang, &cur))).width(200.0).show_ui(
|
craft_ui::ComboBox::from_id_salt(("pslistcs", key))
|
||||||
ui,
|
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(lang, &cur)))
|
||||||
|ui| {
|
.width(200.0)
|
||||||
|
.show_ui(ui, |ui| {
|
||||||
for n in std::iter::once(designcraft_doc::NO_CHAR_STYLE)
|
for n in std::iter::once(designcraft_doc::NO_CHAR_STYLE)
|
||||||
.chain(styles.iter().map(String::as_str).filter(|n| *n != designcraft_doc::NO_CHAR_STYLE))
|
.chain(styles.iter().map(String::as_str).filter(|n| *n != designcraft_doc::NO_CHAR_STYLE))
|
||||||
{
|
{
|
||||||
@@ -5184,8 +5186,7 @@ fn list_char_style(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, ke
|
|||||||
para_set(d, key, json!(n));
|
para_set(d, key, json!(n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The bullet character: common bullets, a field, and the font's glyphs in a grid to pick from.
|
/// The bullet character: common bullets, a field, and the font's glyphs in a grid to pick from.
|
||||||
@@ -5244,7 +5245,7 @@ fn bullet_font(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, lu: &L
|
|||||||
let font = para_value(d, pv, "bulletFont").as_str().unwrap_or("").to_string();
|
let font = para_value(d, pv, "bulletFont").as_str().unwrap_or("").to_string();
|
||||||
let inherit = crate::i18n::tr(lang, "(Paragraph Font)");
|
let inherit = crate::i18n::tr(lang, "(Paragraph Font)");
|
||||||
crate::rtl::label(ui, crate::i18n::tr(lang, "Font Family:"));
|
crate::rtl::label(ui, crate::i18n::tr(lang, "Font Family:"));
|
||||||
egui::ComboBox::from_id_salt("psbulletfont").selected_text(if font.is_empty() { inherit } else { font.as_str() }).width(200.0).show_ui(
|
craft_ui::ComboBox::from_id_salt("psbulletfont").selected_text(if font.is_empty() { inherit } else { font.as_str() }).width(200.0).show_ui(
|
||||||
ui,
|
ui,
|
||||||
|ui| {
|
|ui| {
|
||||||
if ui.selectable_label(font.is_empty(), inherit).clicked() {
|
if ui.selectable_label(font.is_empty(), inherit).clicked() {
|
||||||
@@ -5263,7 +5264,7 @@ fn bullet_font(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value, lu: &L
|
|||||||
crate::rtl::label(ui, crate::i18n::tr(lang, "Font Style:"));
|
crate::rtl::label(ui, crate::i18n::tr(lang, "Font Style:"));
|
||||||
let style = para_value(d, pv, "bulletFontStyle").as_str().unwrap_or("").to_string();
|
let style = para_value(d, pv, "bulletFontStyle").as_str().unwrap_or("").to_string();
|
||||||
ui.add_enabled_ui(!font.is_empty(), |ui| {
|
ui.add_enabled_ui(!font.is_empty(), |ui| {
|
||||||
egui::ComboBox::from_id_salt("psbulletstyle").selected_text(style.as_str()).width(200.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("psbulletstyle").selected_text(style.as_str()).width(200.0).show_ui(ui, |ui| {
|
||||||
for st in lu.fonts.styles(&font) {
|
for st in lu.fonts.styles(&font) {
|
||||||
if ui.selectable_label(st == style, &st).clicked() {
|
if ui.selectable_label(st == style, &st).clicked() {
|
||||||
para_set(d, "bulletFontStyle", json!(st));
|
para_set(d, "bulletFontStyle", json!(st));
|
||||||
@@ -5306,7 +5307,7 @@ fn bullets_and_numbering(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Val
|
|||||||
let list = para_value(d, pv, "listName").as_str().unwrap_or("").to_string();
|
let list = para_value(d, pv, "listName").as_str().unwrap_or("").to_string();
|
||||||
// "" is the story's own list.
|
// "" is the story's own list.
|
||||||
let name = |n: &str| if n.is_empty() { crate::i18n::tr(lang, "[Default]").to_string() } else { n.to_string() };
|
let name = |n: &str| if n.is_empty() { crate::i18n::tr(lang, "[Default]").to_string() } else { n.to_string() };
|
||||||
egui::ComboBox::from_id_salt("pslist").selected_text(name(&list)).width(200.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("pslist").selected_text(name(&list)).width(200.0).show_ui(ui, |ui| {
|
||||||
for n in std::iter::once("").chain(doc.settings.lists.iter().map(|l| l.name.as_str())) {
|
for n in std::iter::once("").chain(doc.settings.lists.iter().map(|l| l.name.as_str())) {
|
||||||
if ui.selectable_label(n == list, name(n)).clicked() {
|
if ui.selectable_label(n == list, name(n)).clicked() {
|
||||||
para_set(d, "listName", json!(n));
|
para_set(d, "listName", json!(n));
|
||||||
@@ -5325,7 +5326,7 @@ fn bullets_and_numbering(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Val
|
|||||||
let start = para_value(d, pv, "startAt").as_u64();
|
let start = para_value(d, pv, "startAt").as_u64();
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let shown = crate::i18n::tr(lang, if start.is_some() { "Start At" } else { "Continue from Previous Number" });
|
let shown = crate::i18n::tr(lang, if start.is_some() { "Start At" } else { "Continue from Previous Number" });
|
||||||
egui::ComboBox::from_id_salt("psmode").selected_text(crate::rtl::widget(ui, shown)).width(200.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("psmode").selected_text(crate::rtl::widget(ui, shown)).width(200.0).show_ui(ui, |ui| {
|
||||||
if ui
|
if ui
|
||||||
.selectable_label(start.is_none(), crate::rtl::widget(ui, crate::i18n::tr(lang, "Continue from Previous Number")))
|
.selectable_label(start.is_none(), crate::rtl::widget(ui, crate::i18n::tr(lang, "Continue from Previous Number")))
|
||||||
.clicked()
|
.clicked()
|
||||||
@@ -5352,16 +5353,16 @@ fn bullets_and_numbering(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Val
|
|||||||
para_check(ui, d, pv, "restartNumbers", crate::i18n::tr(lang, "Restart Numbers at This Level After:"));
|
para_check(ui, d, pv, "restartNumbers", crate::i18n::tr(lang, "Restart Numbers at This Level After:"));
|
||||||
let after = para_value(d, pv, "restartAfterLevel").as_u64().unwrap_or(0) as u32;
|
let after = para_value(d, pv, "restartAfterLevel").as_u64().unwrap_or(0) as u32;
|
||||||
let label = |n: u32| if n == 0 { crate::i18n::tr(lang, "Any Previous Level").to_string() } else { n.to_string() };
|
let label = |n: u32| if n == 0 { crate::i18n::tr(lang, "Any Previous Level").to_string() } else { n.to_string() };
|
||||||
egui::ComboBox::from_id_salt("psrestartafter").selected_text(crate::rtl::widget(ui, label(after))).width(140.0).show_ui(
|
craft_ui::ComboBox::from_id_salt("psrestartafter")
|
||||||
ui,
|
.selected_text(crate::rtl::widget(ui, label(after)))
|
||||||
|ui| {
|
.width(140.0)
|
||||||
|
.show_ui(ui, |ui| {
|
||||||
for n in 0..level {
|
for n in 0..level {
|
||||||
if ui.selectable_label(n == after, crate::rtl::widget(ui, label(n))).clicked() {
|
if ui.selectable_label(n == after, crate::rtl::widget(ui, label(n))).clicked() {
|
||||||
para_set(d, "restartAfterLevel", json!(n));
|
para_set(d, "restartAfterLevel", json!(n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
@@ -5497,7 +5498,7 @@ fn character_style_general(
|
|||||||
text_field_named(ui, d, "rename", 220.0, crate::i18n::tr(lang, "Style Name"));
|
text_field_named(ui, d, "rename", 220.0, crate::i18n::tr(lang, "Style Name"));
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
crate::rtl::label(ui, crate::i18n::tr(lang, "Based On:"));
|
crate::rtl::label(ui, crate::i18n::tr(lang, "Based On:"));
|
||||||
let combo = egui::ComboBox::from_id_salt("csbased")
|
let combo = craft_ui::ComboBox::from_id_salt("csbased")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(lang, based)))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(lang, based)))
|
||||||
.width(220.0)
|
.width(220.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -5656,7 +5657,7 @@ fn char_number(ui: &mut egui::Ui, d: &mut Dialog, cf: &CharFields, key: &str, su
|
|||||||
fn char_choice(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, cf: &CharFields, key: &str, opts: &[(Value, &str)]) {
|
fn char_choice(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, cf: &CharFields, key: &str, opts: &[(Value, &str)]) {
|
||||||
let cur = cf.get(d, key);
|
let cur = cf.get(d, key);
|
||||||
let shown = opts.iter().find(|o| o.0 == cur).map_or("", |o| crate::i18n::tr(lang, o.1));
|
let shown = opts.iter().find(|o| o.0 == cur).map_or("", |o| crate::i18n::tr(lang, o.1));
|
||||||
egui::ComboBox::from_id_salt(("cs", key)).selected_text(crate::rtl::widget(ui, shown)).width(200.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt(("cs", key)).selected_text(crate::rtl::widget(ui, shown)).width(200.0).show_ui(ui, |ui| {
|
||||||
if cf.sparse && ui.selectable_label(cur.is_null(), " ").clicked() {
|
if cf.sparse && ui.selectable_label(cur.is_null(), " ").clicked() {
|
||||||
cf.set(d, key, Value::Null);
|
cf.set(d, key, Value::Null);
|
||||||
}
|
}
|
||||||
@@ -5703,22 +5704,29 @@ fn basic_character_formats(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
|||||||
crate::rtl::label(ui, crate::i18n::tr(lang, "Font Family:"));
|
crate::rtl::label(ui, crate::i18n::tr(lang, "Font Family:"));
|
||||||
let fam = cf.get(d, "fontFamily").as_str().unwrap_or("").to_string();
|
let fam = cf.get(d, "fontFamily").as_str().unwrap_or("").to_string();
|
||||||
let shown = if fam.is_empty() { "—".to_string() } else { crate::panels::font_label(app, &menu, &fam) };
|
let shown = if fam.is_empty() { "—".to_string() } else { crate::panels::font_label(app, &menu, &fam) };
|
||||||
egui::ComboBox::from_id_salt("psfam")
|
let picked = craft_ui::ComboBox::from_id_salt("psfam")
|
||||||
.selected_text(shown)
|
.selected_text(shown)
|
||||||
.width(200.0)
|
.width(200.0)
|
||||||
.height(440.0)
|
.height(440.0)
|
||||||
.close_behavior(egui::PopupCloseBehavior::CloseOnClickOutside)
|
.close_behavior(egui::PopupCloseBehavior::CloseOnClickOutside)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui_with_header(
|
||||||
|
ui,
|
||||||
|
|ui| {
|
||||||
if cf.sparse && ui.selectable_label(fam.is_empty(), " ").clicked() {
|
if cf.sparse && ui.selectable_label(fam.is_empty(), " ").clicked() {
|
||||||
cf.set(d, "fontFamily", Value::Null);
|
cf.set(d, "fontFamily", Value::Null);
|
||||||
}
|
}
|
||||||
if let Some(f) = crate::panels::font_menu_body(app, ui, &menu, &fam, 200.0) {
|
crate::panels::font_menu_header(app, ui, &menu, &fam, 200.0)
|
||||||
|
},
|
||||||
|
crate::panels::font_menu_list,
|
||||||
|
)
|
||||||
|
.inner
|
||||||
|
.flatten();
|
||||||
|
if let Some(f) = picked {
|
||||||
cf.set(d, "fontFamily", json!(f.family));
|
cf.set(d, "fontFamily", json!(f.family));
|
||||||
if let Some(style) = f.style {
|
if let Some(style) = f.style {
|
||||||
cf.set(d, "fontStyle", json!(style));
|
cf.set(d, "fontStyle", json!(style));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
crate::rtl::label(ui, crate::i18n::tr(lang, "Font Style:"));
|
crate::rtl::label(ui, crate::i18n::tr(lang, "Font Style:"));
|
||||||
let sty = cf.get(d, "fontStyle").as_str().unwrap_or("").to_string();
|
let sty = cf.get(d, "fontStyle").as_str().unwrap_or("").to_string();
|
||||||
@@ -5729,7 +5737,7 @@ fn basic_character_formats(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialo
|
|||||||
cf.set(d, "fontStyle", if s.trim().is_empty() { Value::Null } else { json!(s) });
|
cf.set(d, "fontStyle", if s.trim().is_empty() { Value::Null } else { json!(s) });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
egui::ComboBox::from_id_salt("pssty").selected_text(&sty).width(200.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("pssty").selected_text(&sty).width(200.0).show_ui(ui, |ui| {
|
||||||
if cf.sparse && ui.selectable_label(sty.is_empty(), " ").clicked() {
|
if cf.sparse && ui.selectable_label(sty.is_empty(), " ").clicked() {
|
||||||
cf.set(d, "fontStyle", Value::Null);
|
cf.set(d, "fontStyle", Value::Null);
|
||||||
}
|
}
|
||||||
@@ -5837,7 +5845,7 @@ fn advanced_character_formats(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, cf:
|
|||||||
let labels: Vec<String> = crate::panels::properties::DIGIT_OPTIONS.iter().map(|o| crate::panels::properties::digit_label(lang, *o)).collect();
|
let labels: Vec<String> = crate::panels::properties::DIGIT_OPTIONS.iter().map(|o| crate::panels::properties::digit_label(lang, *o)).collect();
|
||||||
let cur = cf.get(d, "digits");
|
let cur = cf.get(d, "digits");
|
||||||
let shown = crate::panels::properties::DIGIT_OPTIONS.iter().position(|o| json!(o.0) == cur).map_or(String::new(), |i| labels[i].clone());
|
let shown = crate::panels::properties::DIGIT_OPTIONS.iter().position(|o| json!(o.0) == cur).map_or(String::new(), |i| labels[i].clone());
|
||||||
egui::ComboBox::from_id_salt(("cs", "digits")).selected_text(crate::rtl::widget(ui, &shown)).width(200.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt(("cs", "digits")).selected_text(crate::rtl::widget(ui, &shown)).width(200.0).show_ui(ui, |ui| {
|
||||||
if cf.sparse && ui.selectable_label(cur.is_null(), " ").clicked() {
|
if cf.sparse && ui.selectable_label(cur.is_null(), " ").clicked() {
|
||||||
cf.set(d, "digits", Value::Null);
|
cf.set(d, "digits", Value::Null);
|
||||||
}
|
}
|
||||||
@@ -5913,14 +5921,18 @@ fn open_type_features(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, cf: &CharFi
|
|||||||
crate::rtl::label(ui, crate::i18n::tr(lang, "Figure Style:"));
|
crate::rtl::label(ui, crate::i18n::tr(lang, "Figure Style:"));
|
||||||
let fig = otf::figures(&list);
|
let fig = otf::figures(&list);
|
||||||
let shown = otf::FIGURES.iter().find(|f| f.0 == fig).map_or("", |f| f.1);
|
let shown = otf::FIGURES.iter().find(|f| f.0 == fig).map_or("", |f| f.1);
|
||||||
egui::ComboBox::from_id_salt("csfig").selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, shown))).width(180.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("csfig").selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, shown))).width(180.0).show_ui(
|
||||||
|
ui,
|
||||||
|
|ui| {
|
||||||
for (id, label, ..) in otf::FIGURES {
|
for (id, label, ..) in otf::FIGURES {
|
||||||
if ui.selectable_label(fig == *id, crate::rtl::widget(ui, crate::i18n::tr(lang, label))).clicked() && otf::set_figures(&mut list, id)
|
if ui.selectable_label(fig == *id, crate::rtl::widget(ui, crate::i18n::tr(lang, label))).clicked()
|
||||||
|
&& otf::set_figures(&mut list, id)
|
||||||
{
|
{
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
ui.add_space(4.0);
|
ui.add_space(4.0);
|
||||||
crate::rtl::label(ui, crate::i18n::tr(lang, "Stylistic Sets"));
|
crate::rtl::label(ui, crate::i18n::tr(lang, "Stylistic Sets"));
|
||||||
@@ -5995,7 +6007,7 @@ fn delete_character_style(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog
|
|||||||
d.fields.insert("replaceWith".into(), json!(designcraft_doc::NO_CHAR_STYLE));
|
d.fields.insert("replaceWith".into(), json!(designcraft_doc::NO_CHAR_STYLE));
|
||||||
}
|
}
|
||||||
let replace = d.s("replaceWith");
|
let replace = d.s("replaceWith");
|
||||||
egui::ComboBox::from_id_salt("del_char_replace")
|
craft_ui::ComboBox::from_id_salt("del_char_replace")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, &replace)))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, &replace)))
|
||||||
.width(260.0)
|
.width(260.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -6010,7 +6022,7 @@ fn delete_character_style(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog
|
|||||||
fn combo(ui: &mut egui::Ui, d: &mut Dialog, key: &str, opts: &[(&str, &str)]) {
|
fn combo(ui: &mut egui::Ui, d: &mut Dialog, key: &str, opts: &[(&str, &str)]) {
|
||||||
let cur = d.s(key);
|
let cur = d.s(key);
|
||||||
let shown = opts.iter().find(|o| o.0 == cur).map_or(cur.as_str(), |o| o.1).to_string();
|
let shown = opts.iter().find(|o| o.0 == cur).map_or(cur.as_str(), |o| o.1).to_string();
|
||||||
egui::ComboBox::from_id_salt(key).selected_text(crate::rtl::widget(ui, &shown)).width(170.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt(key).selected_text(crate::rtl::widget(ui, &shown)).width(170.0).show_ui(ui, |ui| {
|
||||||
for (v, label) in opts {
|
for (v, label) in opts {
|
||||||
if ui.selectable_label(cur == *v, crate::rtl::widget(ui, *label)).clicked() {
|
if ui.selectable_label(cur == *v, crate::rtl::widget(ui, *label)).clicked() {
|
||||||
d.fields.insert(key.into(), json!(v));
|
d.fields.insert(key.into(), json!(v));
|
||||||
@@ -6351,7 +6363,7 @@ fn paragraph_rules(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog, prefix: &
|
|||||||
};
|
};
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let shown = RULES.iter().find(|r| r.0 == which).map_or(which, |r| r.1);
|
let shown = RULES.iter().find(|r| r.0 == which).map_or(which, |r| r.1);
|
||||||
egui::ComboBox::from_id_salt("rule_which").selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, shown))).width(130.0).show_ui(
|
craft_ui::ComboBox::from_id_salt("rule_which").selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, shown))).width(130.0).show_ui(
|
||||||
ui,
|
ui,
|
||||||
|ui| {
|
|ui| {
|
||||||
for (v, label) in RULES {
|
for (v, label) in RULES {
|
||||||
@@ -6387,7 +6399,7 @@ fn paragraph_rules(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog, prefix: &
|
|||||||
}
|
}
|
||||||
crate::rtl::label(ui, crate::i18n::tr(lang, "Width:"));
|
crate::rtl::label(ui, crate::i18n::tr(lang, "Width:"));
|
||||||
let column = rule["columnWidth"].as_bool().unwrap_or(true);
|
let column = rule["columnWidth"].as_bool().unwrap_or(true);
|
||||||
egui::ComboBox::from_id_salt(("rule_width", which))
|
craft_ui::ComboBox::from_id_salt(("rule_width", which))
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, if column { "Column" } else { "Text" })))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(lang, if column { "Column" } else { "Text" })))
|
||||||
.width(130.0)
|
.width(130.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -6794,7 +6806,7 @@ fn toc_params(app: &DesignApp, d: &Dialog) -> Value {
|
|||||||
fn toc_style_combo(ui: &mut egui::Ui, salt: &str, styles: &[String], auto: &str, cur: &mut String) -> bool {
|
fn toc_style_combo(ui: &mut egui::Ui, salt: &str, styles: &[String], auto: &str, cur: &mut String) -> bool {
|
||||||
let shown = if cur.is_empty() { auto.to_string() } else { cur.clone() };
|
let shown = if cur.is_empty() { auto.to_string() } else { cur.clone() };
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
egui::ComboBox::from_id_salt(("toc_style", salt)).selected_text(shown).width(200.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt(("toc_style", salt)).selected_text(shown).width(200.0).show_ui(ui, |ui| {
|
||||||
if ui.selectable_label(cur.is_empty(), auto).clicked() {
|
if ui.selectable_label(cur.is_empty(), auto).clicked() {
|
||||||
cur.clear();
|
cur.clear();
|
||||||
changed = true;
|
changed = true;
|
||||||
@@ -6885,7 +6897,7 @@ fn toc_dialog(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
|||||||
crate::rtl::label(ui, tr("Page Number:"));
|
crate::rtl::label(ui, tr("Page Number:"));
|
||||||
let choices = [("after", "After Entry"), ("before", "Before Entry"), ("none", "No Page Number")];
|
let choices = [("after", "After Entry"), ("before", "Before Entry"), ("none", "No Page Number")];
|
||||||
let cur = choices.iter().find(|(v, _)| *v == r.page_number).map_or("After Entry", |(_, l)| l);
|
let cur = choices.iter().find(|(v, _)| *v == r.page_number).map_or("After Entry", |(_, l)| l);
|
||||||
egui::ComboBox::from_id_salt("toc_page_number").selected_text(tr(cur)).width(200.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("toc_page_number").selected_text(tr(cur)).width(200.0).show_ui(ui, |ui| {
|
||||||
for (v, l) in choices {
|
for (v, l) in choices {
|
||||||
if ui.selectable_label(r.page_number == v, tr(l)).clicked() {
|
if ui.selectable_label(r.page_number == v, tr(l)).clicked() {
|
||||||
r.page_number = v.into();
|
r.page_number = v.into();
|
||||||
@@ -6904,7 +6916,7 @@ fn toc_dialog(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
|||||||
ui.checkbox(&mut r.sort, tr("Sort Entries in Alphabetical Order"));
|
ui.checkbox(&mut r.sort, tr("Sort Entries in Alphabetical Order"));
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
crate::rtl::label(ui, tr("Level:"));
|
crate::rtl::label(ui, tr("Level:"));
|
||||||
egui::ComboBox::from_id_salt("toc_level").selected_text(r.level.to_string()).width(60.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("toc_level").selected_text(r.level.to_string()).width(60.0).show_ui(ui, |ui| {
|
||||||
for l in 1..=9u8 {
|
for l in 1..=9u8 {
|
||||||
if ui.selectable_label(r.level == l, l.to_string()).clicked() {
|
if ui.selectable_label(r.level == l, l.to_string()).clicked() {
|
||||||
r.level = l;
|
r.level = l;
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ pub fn swatch_options(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
|||||||
if kind == "color" {
|
if kind == "color" {
|
||||||
caption(ui, lang, "Color Type:");
|
caption(ui, lang, "Color Type:");
|
||||||
let cur = d.s("colorType");
|
let cur = d.s("colorType");
|
||||||
let combo = egui::ComboBox::from_id_salt("swatch_color_type")
|
let combo = craft_ui::ComboBox::from_id_salt("swatch_color_type")
|
||||||
.selected_text(crate::rtl::widget(ui, tr(lang, if cur == "spot" { "Spot" } else { "Process" })))
|
.selected_text(crate::rtl::widget(ui, tr(lang, if cur == "spot" { "Spot" } else { "Process" })))
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
for (v, l) in [("process", "Process"), ("spot", "Spot")] {
|
for (v, l) in [("process", "Process"), ("spot", "Spot")] {
|
||||||
@@ -149,9 +149,9 @@ pub fn swatch_options(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
|||||||
"gray" => "Gray",
|
"gray" => "Gray",
|
||||||
_ => "CMYK",
|
_ => "CMYK",
|
||||||
};
|
};
|
||||||
let combo = egui::ComboBox::from_id_salt("swatch_color_mode").selected_text(crate::rtl::widget(ui, tr(lang, label(&cur)))).show_ui(
|
let combo = craft_ui::ComboBox::from_id_salt("swatch_color_mode")
|
||||||
ui,
|
.selected_text(crate::rtl::widget(ui, tr(lang, label(&cur))))
|
||||||
|ui| {
|
.show_ui(ui, |ui| {
|
||||||
for m in ["cmyk", "rgb", "gray"] {
|
for m in ["cmyk", "rgb", "gray"] {
|
||||||
if ui.selectable_label(cur == m, crate::rtl::widget(ui, tr(lang, label(m)))).clicked()
|
if ui.selectable_label(cur == m, crate::rtl::widget(ui, tr(lang, label(m)))).clicked()
|
||||||
&& cur != m
|
&& cur != m
|
||||||
@@ -160,8 +160,7 @@ pub fn swatch_options(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
|||||||
set_color(&mut d.fields, c, Some(m));
|
set_color(&mut d.fields, c, Some(m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
let _ = crate::widgets::name_combo(combo, tr(lang, "Color Mode"));
|
let _ = crate::widgets::name_combo(combo, tr(lang, "Color Mode"));
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
match d.s("mode").as_str() {
|
match d.s("mode").as_str() {
|
||||||
@@ -283,7 +282,7 @@ pub fn layer_options(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
|||||||
ui.end_row();
|
ui.end_row();
|
||||||
caption(ui, lang, "Color:");
|
caption(ui, lang, "Color:");
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let combo = egui::ComboBox::from_id_salt("layer_color")
|
let combo = craft_ui::ComboBox::from_id_salt("layer_color")
|
||||||
.selected_text(crate::rtl::widget(ui, tr(lang, named.unwrap_or("Custom"))))
|
.selected_text(crate::rtl::widget(ui, tr(lang, named.unwrap_or("Custom"))))
|
||||||
.width(140.0)
|
.width(140.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
|
|||||||
@@ -143,12 +143,14 @@ fn font_fields(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog, cf: &Char
|
|||||||
};
|
};
|
||||||
crate::rtl::label(ui, tr(lang, "Font Family:"));
|
crate::rtl::label(ui, tr(lang, "Font Family:"));
|
||||||
ui.add_enabled_ui(enabled, |ui| {
|
ui.add_enabled_ui(enabled, |ui| {
|
||||||
egui::ComboBox::from_id_salt(("cjkfam", fam_key))
|
let picked = craft_ui::ComboBox::from_id_salt(("cjkfam", fam_key))
|
||||||
.selected_text(shown)
|
.selected_text(shown)
|
||||||
.width(200.0)
|
.width(200.0)
|
||||||
.height(440.0)
|
.height(440.0)
|
||||||
.close_behavior(egui::PopupCloseBehavior::CloseOnClickOutside)
|
.close_behavior(egui::PopupCloseBehavior::CloseOnClickOutside)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui_with_header(
|
||||||
|
ui,
|
||||||
|
|ui| {
|
||||||
if cf.sparse && ui.selectable_label(raw.is_null(), " ").clicked() {
|
if cf.sparse && ui.selectable_label(raw.is_null(), " ").clicked() {
|
||||||
cf.set(d, fam_key, Value::Null);
|
cf.set(d, fam_key, Value::Null);
|
||||||
cf.set(d, style_key, Value::Null);
|
cf.set(d, style_key, Value::Null);
|
||||||
@@ -157,19 +159,24 @@ fn font_fields(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog, cf: &Char
|
|||||||
cf.set(d, fam_key, json!(""));
|
cf.set(d, fam_key, json!(""));
|
||||||
cf.set(d, style_key, json!(""));
|
cf.set(d, style_key, json!(""));
|
||||||
}
|
}
|
||||||
if let Some(f) = crate::panels::font_menu_body(app, ui, &menu, &fam, 200.0) {
|
crate::panels::font_menu_header(app, ui, &menu, &fam, 200.0)
|
||||||
|
},
|
||||||
|
crate::panels::font_menu_list,
|
||||||
|
)
|
||||||
|
.inner
|
||||||
|
.flatten();
|
||||||
|
if let Some(f) = picked {
|
||||||
cf.set(d, fam_key, json!(f.family));
|
cf.set(d, fam_key, json!(f.family));
|
||||||
if let Some(style) = f.style {
|
if let Some(style) = f.style {
|
||||||
cf.set(d, style_key, json!(style));
|
cf.set(d, style_key, json!(style));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
crate::rtl::label(ui, tr(lang, "Font Style:"));
|
crate::rtl::label(ui, tr(lang, "Font Style:"));
|
||||||
let sty = cf.get(d, style_key).as_str().unwrap_or("").to_string();
|
let sty = cf.get(d, style_key).as_str().unwrap_or("").to_string();
|
||||||
ui.add_enabled_ui(enabled && !fam.is_empty(), |ui| {
|
ui.add_enabled_ui(enabled && !fam.is_empty(), |ui| {
|
||||||
egui::ComboBox::from_id_salt(("cjksty", style_key)).selected_text(&sty).width(200.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt(("cjksty", style_key)).selected_text(&sty).width(200.0).show_ui(ui, |ui| {
|
||||||
for s in fonts.styles(&fam) {
|
for s in fonts.styles(&fam) {
|
||||||
if ui.selectable_label(s == sty, &s).clicked() {
|
if ui.selectable_label(s == sty, &s).clicked() {
|
||||||
cf.set(d, style_key, json!(s));
|
cf.set(d, style_key, json!(s));
|
||||||
@@ -527,7 +534,7 @@ fn kenten(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog, cf: &CharField
|
|||||||
Some(false) => tr(lang, "None").to_string(),
|
Some(false) => tr(lang, "None").to_string(),
|
||||||
Some(true) => tr(lang, kenten_label(kind)).to_string(),
|
Some(true) => tr(lang, kenten_label(kind)).to_string(),
|
||||||
};
|
};
|
||||||
egui::ComboBox::from_id_salt("cjkkententype").selected_text(crate::rtl::widget(ui, shown)).width(200.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("cjkkententype").selected_text(crate::rtl::widget(ui, shown)).width(200.0).show_ui(ui, |ui| {
|
||||||
if cf.sparse && ui.selectable_label(on.is_none(), " ").clicked() {
|
if cf.sparse && ui.selectable_label(on.is_none(), " ").clicked() {
|
||||||
for key in ["kenten", "kentenKind", "kentenCharacter"] {
|
for key in ["kenten", "kentenKind", "kentenCharacter"] {
|
||||||
cf.set(d, key, Value::Null);
|
cf.set(d, key, Value::Null);
|
||||||
@@ -654,7 +661,7 @@ fn para_value(d: &Dialog, pv: &Value, key: &str) -> Value {
|
|||||||
/// A paragraph attribute from `opts` (value, label); `current` is the value shown.
|
/// A paragraph attribute from `opts` (value, label); `current` is the value shown.
|
||||||
fn para_choice(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, key: &str, current: &str, opts: &[(&str, &str)]) {
|
fn para_choice(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, key: &str, current: &str, opts: &[(&str, &str)]) {
|
||||||
let shown = opts.iter().find(|o| o.0 == current).map_or("", |o| crate::i18n::tr(lang, o.1));
|
let shown = opts.iter().find(|o| o.0 == current).map_or("", |o| crate::i18n::tr(lang, o.1));
|
||||||
egui::ComboBox::from_id_salt(("cjkp", key)).selected_text(crate::rtl::widget(ui, shown)).width(220.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt(("cjkp", key)).selected_text(crate::rtl::widget(ui, shown)).width(220.0).show_ui(ui, |ui| {
|
||||||
for (v, label) in opts {
|
for (v, label) in opts {
|
||||||
if ui.selectable_label(*v == current, crate::rtl::widget(ui, crate::i18n::tr(lang, label))).clicked() {
|
if ui.selectable_label(*v == current, crate::rtl::widget(ui, crate::i18n::tr(lang, label))).clicked() {
|
||||||
d.fields.insert(format!("p.{key}"), json!(v));
|
d.fields.insert(format!("p.{key}"), json!(v));
|
||||||
@@ -731,7 +738,7 @@ fn japanese_composition(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, cf: &Char
|
|||||||
// `null`: no set given, so the composer's default rules apply.
|
// `null`: no set given, so the composer's default rules apply.
|
||||||
let name = para_value(d, pv, "kinsoku").get("name").and_then(Value::as_str).map(str::to_string);
|
let name = para_value(d, pv, "kinsoku").get("name").and_then(Value::as_str).map(str::to_string);
|
||||||
let shown = name.as_deref().map_or_else(|| crate::i18n::tr(lang, "Default Rules").to_string(), |n| kinsoku_label(lang, n));
|
let shown = name.as_deref().map_or_else(|| crate::i18n::tr(lang, "Default Rules").to_string(), |n| kinsoku_label(lang, n));
|
||||||
egui::ComboBox::from_id_salt("cjkkinsoku").selected_text(crate::rtl::widget(ui, shown)).width(220.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("cjkkinsoku").selected_text(crate::rtl::widget(ui, shown)).width(220.0).show_ui(ui, |ui| {
|
||||||
// `style.paragraph.edit` takes `null` as the default rules, also over a Based On set.
|
// `style.paragraph.edit` takes `null` as the default rules, also over a Based On set.
|
||||||
if ui.selectable_label(name.is_none(), crate::rtl::widget(ui, crate::i18n::tr(lang, "Default Rules"))).clicked() {
|
if ui.selectable_label(name.is_none(), crate::rtl::widget(ui, crate::i18n::tr(lang, "Default Rules"))).clicked() {
|
||||||
d.fields.insert("p.kinsoku".into(), Value::Null);
|
d.fields.insert("p.kinsoku".into(), Value::Null);
|
||||||
@@ -780,7 +787,7 @@ fn japanese_composition(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, cf: &Char
|
|||||||
let sets = mojikumi_sets(doc, ¤t);
|
let sets = mojikumi_sets(doc, ¤t);
|
||||||
let label = |l: &str| if l.is_empty() { crate::i18n::tr(lang, "None").to_string() } else { l.to_string() };
|
let label = |l: &str| if l.is_empty() { crate::i18n::tr(lang, "None").to_string() } else { l.to_string() };
|
||||||
let shown = sets.iter().find(|s| s.0 == current).map_or_else(String::new, |s| label(s.1.as_str()));
|
let shown = sets.iter().find(|s| s.0 == current).map_or_else(String::new, |s| label(s.1.as_str()));
|
||||||
egui::ComboBox::from_id_salt("cjkmojikumi").selected_text(crate::rtl::widget(ui, shown)).width(220.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("cjkmojikumi").selected_text(crate::rtl::widget(ui, shown)).width(220.0).show_ui(ui, |ui| {
|
||||||
for (v, l) in &sets {
|
for (v, l) in &sets {
|
||||||
if ui.selectable_label(*v == current, crate::rtl::widget(ui, label(l.as_str()))).clicked() {
|
if ui.selectable_label(*v == current, crate::rtl::widget(ui, label(l.as_str()))).clicked() {
|
||||||
d.fields.insert("p.mojikumi".into(), json!(v));
|
d.fields.insert("p.mojikumi".into(), json!(v));
|
||||||
@@ -834,7 +841,7 @@ fn grid_settings(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, pv: &Value) {
|
|||||||
grid("cjkgrid").show(ui, |ui| {
|
grid("cjkgrid").show(ui, |ui| {
|
||||||
crate::rtl::label(ui, tr(lang, "Grid Alignment:"));
|
crate::rtl::label(ui, tr(lang, "Grid Alignment:"));
|
||||||
let shown = if on { REFERENCES.iter().find(|r| r.0 == reference).map_or("", |r| r.1) } else { "None" };
|
let shown = if on { REFERENCES.iter().find(|r| r.0 == reference).map_or("", |r| r.1) } else { "None" };
|
||||||
egui::ComboBox::from_id_salt("cjkgridalign").selected_text(crate::rtl::widget(ui, tr(lang, shown))).width(220.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("cjkgridalign").selected_text(crate::rtl::widget(ui, tr(lang, shown))).width(220.0).show_ui(ui, |ui| {
|
||||||
if ui.selectable_label(!on, crate::rtl::widget(ui, tr(lang, "None"))).clicked() {
|
if ui.selectable_label(!on, crate::rtl::widget(ui, tr(lang, "None"))).clicked() {
|
||||||
set(d, GridAlign::None);
|
set(d, GridAlign::None);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ fn swatch(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog, path: &[&str]) {
|
|||||||
.session
|
.session
|
||||||
.active()
|
.active()
|
||||||
.map_or_else(Vec::new, |st| st.doc.swatches.iter().filter(|w| !w.hidden || w.name == cur).map(|w| w.name.clone()).collect());
|
.map_or_else(Vec::new, |st| st.doc.swatches.iter().filter(|w| !w.hidden || w.name == cur).map(|w| w.name.clone()).collect());
|
||||||
egui::ComboBox::from_id_salt(("fx_swatch", path.join("."))).selected_text(&cur).width(150.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt(("fx_swatch", path.join("."))).selected_text(&cur).width(150.0).show_ui(ui, |ui| {
|
||||||
for n in names {
|
for n in names {
|
||||||
if ui.selectable_label(n == cur, &n).clicked() {
|
if ui.selectable_label(n == cur, &n).clicked() {
|
||||||
set(d, path, json!(n));
|
set(d, path, json!(n));
|
||||||
@@ -299,7 +299,7 @@ fn page_ui(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog, page: &str) {
|
|||||||
grid("t").show(ui, |ui| {
|
grid("t").show(ui, |ui| {
|
||||||
row(ui, "Mode:");
|
row(ui, "Mode:");
|
||||||
let cur = d.fields.get("blend").and_then(Value::as_str).unwrap_or("Normal").to_string();
|
let cur = d.fields.get("blend").and_then(Value::as_str).unwrap_or("Normal").to_string();
|
||||||
egui::ComboBox::from_id_salt("fx_blend").selected_text(tr(&cur)).width(150.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("fx_blend").selected_text(tr(&cur)).width(150.0).show_ui(ui, |ui| {
|
||||||
for m in designcraft_color::BlendMode::ALL {
|
for m in designcraft_color::BlendMode::ALL {
|
||||||
if ui.selectable_label(m.label() == cur, tr(m.label())).clicked() {
|
if ui.selectable_label(m.label() == cur, tr(m.label())).clicked() {
|
||||||
d.fields.insert("blend".into(), json!(m.label()));
|
d.fields.insert("blend".into(), json!(m.label()));
|
||||||
@@ -367,7 +367,7 @@ fn page_ui(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog, page: &str) {
|
|||||||
serde_json::to_value(m).ok().and_then(|v| v.as_str().map(str::to_string)).unwrap_or_default()
|
serde_json::to_value(m).ok().and_then(|v| v.as_str().map(str::to_string)).unwrap_or_default()
|
||||||
};
|
};
|
||||||
let shown = designcraft_color::BlendMode::ALL.iter().find(|m| label(m) == cur).map_or("Screen", |m| m.label());
|
let shown = designcraft_color::BlendMode::ALL.iter().find(|m| label(m) == cur).map_or("Screen", |m| m.label());
|
||||||
egui::ComboBox::from_id_salt("fx_glow_mode").selected_text(tr(shown)).width(150.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("fx_glow_mode").selected_text(tr(shown)).width(150.0).show_ui(ui, |ui| {
|
||||||
for m in designcraft_color::BlendMode::ALL {
|
for m in designcraft_color::BlendMode::ALL {
|
||||||
if ui.selectable_label(label(&m) == cur, tr(m.label())).clicked() {
|
if ui.selectable_label(label(&m) == cur, tr(m.label())).clicked() {
|
||||||
set(d, &["innerGlow", "mode"], json!(label(&m)));
|
set(d, &["innerGlow", "mode"], json!(label(&m)));
|
||||||
@@ -395,7 +395,7 @@ fn page_ui(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog, page: &str) {
|
|||||||
ui.end_row();
|
ui.end_row();
|
||||||
row(ui, "Technique:");
|
row(ui, "Technique:");
|
||||||
let cur = d.fields.get("fx").and_then(|f| f["innerGlow"]["technique"].as_str()).unwrap_or("softer").to_string();
|
let cur = d.fields.get("fx").and_then(|f| f["innerGlow"]["technique"].as_str()).unwrap_or("softer").to_string();
|
||||||
egui::ComboBox::from_id_salt("fx_technique").selected_text(tr(if cur == "precise" { "Precise" } else { "Softer" })).show_ui(
|
craft_ui::ComboBox::from_id_salt("fx_technique").selected_text(tr(if cur == "precise" { "Precise" } else { "Softer" })).show_ui(
|
||||||
ui,
|
ui,
|
||||||
|ui| {
|
|ui| {
|
||||||
for (v, l) in [("softer", "Softer"), ("precise", "Precise")] {
|
for (v, l) in [("softer", "Softer"), ("precise", "Precise")] {
|
||||||
@@ -409,7 +409,7 @@ fn page_ui(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog, page: &str) {
|
|||||||
row(ui, "Source:");
|
row(ui, "Source:");
|
||||||
let mut center = d.fields.get("fx").is_some_and(|f| f["innerGlow"]["center"].as_bool().unwrap_or(false));
|
let mut center = d.fields.get("fx").is_some_and(|f| f["innerGlow"]["center"].as_bool().unwrap_or(false));
|
||||||
let label = |c: bool| tr(if c { "Center" } else { "Edge" });
|
let label = |c: bool| tr(if c { "Center" } else { "Edge" });
|
||||||
egui::ComboBox::from_id_salt("fx_source").selected_text(label(center)).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("fx_source").selected_text(label(center)).show_ui(ui, |ui| {
|
||||||
for c in [false, true] {
|
for c in [false, true] {
|
||||||
if ui.selectable_value(&mut center, c, label(c)).clicked() {
|
if ui.selectable_value(&mut center, c, label(c)).clicked() {
|
||||||
set(d, &["innerGlow", "center"], json!(c));
|
set(d, &["innerGlow", "center"], json!(c));
|
||||||
@@ -490,7 +490,7 @@ fn page_ui(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog, page: &str) {
|
|||||||
"rounded" => "Rounded",
|
"rounded" => "Rounded",
|
||||||
_ => "Diffused",
|
_ => "Diffused",
|
||||||
};
|
};
|
||||||
egui::ComboBox::from_id_salt("fx_corners").selected_text(tr(shown)).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("fx_corners").selected_text(tr(shown)).show_ui(ui, |ui| {
|
||||||
for (v, l) in [("sharp", "Sharp"), ("rounded", "Rounded"), ("diffused", "Diffused")] {
|
for (v, l) in [("sharp", "Sharp"), ("rounded", "Rounded"), ("diffused", "Diffused")] {
|
||||||
if ui.selectable_label(cur == v, tr(l)).clicked() {
|
if ui.selectable_label(cur == v, tr(l)).clicked() {
|
||||||
set(d, &["featherOptions", "corners"], json!(v));
|
set(d, &["featherOptions", "corners"], json!(v));
|
||||||
@@ -539,7 +539,7 @@ fn page_ui(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog, page: &str) {
|
|||||||
row(ui, "Type:");
|
row(ui, "Type:");
|
||||||
let mut radial = d.fields.get("fx").is_some_and(|f| f["gradientFeather"]["radial"].as_bool().unwrap_or(false));
|
let mut radial = d.fields.get("fx").is_some_and(|f| f["gradientFeather"]["radial"].as_bool().unwrap_or(false));
|
||||||
let label = |r: bool| tr(if r { "Radial" } else { "Linear" });
|
let label = |r: bool| tr(if r { "Radial" } else { "Linear" });
|
||||||
egui::ComboBox::from_id_salt("fx_gtype").selected_text(label(radial)).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("fx_gtype").selected_text(label(radial)).show_ui(ui, |ui| {
|
||||||
for r in [false, true] {
|
for r in [false, true] {
|
||||||
if ui.selectable_value(&mut radial, r, label(r)).clicked() {
|
if ui.selectable_value(&mut radial, r, label(r)).clicked() {
|
||||||
set(d, &["gradientFeather", "radial"], json!(r));
|
set(d, &["gradientFeather", "radial"], json!(r));
|
||||||
@@ -573,7 +573,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
|||||||
crate::rtl::label(ui, tr("Settings for:"));
|
crate::rtl::label(ui, tr("Settings for:"));
|
||||||
// Stroke, Fill and Text levels aren't in the document model yet: the object only.
|
// Stroke, Fill and Text levels aren't in the document model yet: the object only.
|
||||||
ui.add_enabled_ui(false, |ui| {
|
ui.add_enabled_ui(false, |ui| {
|
||||||
egui::ComboBox::from_id_salt("fx_level").selected_text(tr("Object")).width(110.0).show_ui(ui, |_| {});
|
craft_ui::ComboBox::from_id_salt("fx_level").selected_text(tr("Object")).width(110.0).show_ui(ui, |_| {});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
|
|||||||
@@ -771,14 +771,17 @@ fn details(app: &mut DesignApp, ui: &mut Ui, d: &mut Dialog) {
|
|||||||
row(ui, rtl, |ui| {
|
row(ui, rtl, |ui| {
|
||||||
cell(ui, rtl, tr("Width"), |ui| spin(ui, d, "width", COLUMN_W - 8.0, Step::Measure(1.0)));
|
cell(ui, rtl, tr("Width"), |ui| spin(ui, d, "width", COLUMN_W - 8.0, Step::Measure(1.0)));
|
||||||
cell(ui, rtl, tr("Units"), |ui| {
|
cell(ui, rtl, tr("Units"), |ui| {
|
||||||
egui::ComboBox::from_id_salt("nd_units").selected_text(crate::rtl::widget(ui, tr(u.label()))).width(COLUMN_W - 8.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("nd_units").selected_text(crate::rtl::widget(ui, tr(u.label()))).width(COLUMN_W - 8.0).show_ui(
|
||||||
|
ui,
|
||||||
|
|ui| {
|
||||||
// InDesign's eight; a preset in another unit keeps it on the list.
|
// InDesign's eight; a preset in another unit keeps it on the list.
|
||||||
for v in NEW_DOCUMENT_UNITS.into_iter().chain((!NEW_DOCUMENT_UNITS.contains(&u)).then_some(u)) {
|
for v in NEW_DOCUMENT_UNITS.into_iter().chain((!NEW_DOCUMENT_UNITS.contains(&u)).then_some(u)) {
|
||||||
if ui.selectable_label(v == u, crate::rtl::widget(ui, tr(v.label()))).clicked() && v != u {
|
if ui.selectable_label(v == u, crate::rtl::widget(ui, tr(v.label()))).clicked() && v != u {
|
||||||
set_units(d, v);
|
set_units(d, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
row(ui, rtl, |ui| {
|
row(ui, rtl, |ui| {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
pub mod cell_stroke;
|
pub mod cell_stroke;
|
||||||
pub mod conditions;
|
pub mod conditions;
|
||||||
mod font_menu;
|
mod font_menu;
|
||||||
pub use font_menu::{FontPick, SAMPLES as FONT_SAMPLES, font_menu_body};
|
pub use font_menu::{FONT_MENU_HEIGHT, FontMenu, FontPick, SAMPLES as FONT_SAMPLES, font_menu_header, font_menu_list};
|
||||||
pub mod datamerge;
|
pub mod datamerge;
|
||||||
pub mod glyphs;
|
pub mod glyphs;
|
||||||
pub mod interactive;
|
pub mod interactive;
|
||||||
@@ -383,7 +383,8 @@ pub fn swatch_picker(
|
|||||||
Some(resp)
|
Some(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A font family combo box showing `current` by its menu name, with [`font_menu_body`] as its menu.
|
/// A font family combo box showing `current` by its menu name, with the Font menu
|
||||||
|
/// ([`font_menu_header`]) as its menu.
|
||||||
/// Returns the font picked.
|
/// Returns the font picked.
|
||||||
pub fn font_combo(
|
pub fn font_combo(
|
||||||
app: &mut DesignApp,
|
app: &mut DesignApp,
|
||||||
@@ -394,15 +395,20 @@ pub fn font_combo(
|
|||||||
) -> Option<FontPick> {
|
) -> Option<FontPick> {
|
||||||
let menu = font_menu(app);
|
let menu = font_menu(app);
|
||||||
let shown = if current.is_empty() { "—".to_string() } else { font_label(app, &menu, current) };
|
let shown = if current.is_empty() { "—".to_string() } else { font_label(app, &menu, current) };
|
||||||
// A field and a plain popup rather than egui's combo box: its own scroll area would keep the
|
|
||||||
// menu at the size it last had (a family opening, a filter clearing, wouldn't show).
|
|
||||||
let field = ui.push_id(id_salt, |ui| crate::widgets::dropdown(ui, &shown, width)).inner;
|
let field = ui.push_id(id_salt, |ui| crate::widgets::dropdown(ui, &shown, width)).inner;
|
||||||
font_popup(app, &field, &menu, current)
|
font_popup(app, ui, &field, &menu, current)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [`font_menu_body`] in a popup under `field` (a font field the caller draws), which screen
|
/// The Font menu ([`font_menu_header`]) in a menu under `field` (a font field the caller draws in
|
||||||
/// readers hear as a combo box with the current family as its value. Returns the font picked.
|
/// `ui`), which screen readers hear as a combo box with the current family as its value. Returns
|
||||||
pub fn font_popup(app: &mut DesignApp, field: &egui::Response, menu: &[designcraft_fonts::FamilyInfo], current: &str) -> Option<FontPick> {
|
/// the font picked.
|
||||||
|
pub fn font_popup(
|
||||||
|
app: &mut DesignApp,
|
||||||
|
ui: &egui::Ui,
|
||||||
|
field: &egui::Response,
|
||||||
|
menu: &[designcraft_fonts::FamilyInfo],
|
||||||
|
current: &str,
|
||||||
|
) -> Option<FontPick> {
|
||||||
let shown = if current.is_empty() { "—".to_string() } else { font_label(app, menu, current) };
|
let shown = if current.is_empty() { "—".to_string() } else { font_label(app, menu, current) };
|
||||||
field.widget_info(|| {
|
field.widget_info(|| {
|
||||||
let mut info = egui::WidgetInfo::new(egui::Role::ComboBox);
|
let mut info = egui::WidgetInfo::new(egui::Role::ComboBox);
|
||||||
@@ -411,10 +417,12 @@ pub fn font_popup(app: &mut DesignApp, field: &egui::Response, menu: &[designcra
|
|||||||
info.label = Some(crate::i18n::tr(&app.ui.language, "Font Family").to_owned());
|
info.label = Some(crate::i18n::tr(&app.ui.language, "Font Family").to_owned());
|
||||||
info
|
info
|
||||||
});
|
});
|
||||||
egui::Popup::menu(field)
|
let width = field.rect.width();
|
||||||
|
craft_ui::combo::Menu::new(ui, field)
|
||||||
|
.height(FONT_MENU_HEIGHT)
|
||||||
.close_behavior(egui::PopupCloseBehavior::CloseOnClickOutside)
|
.close_behavior(egui::PopupCloseBehavior::CloseOnClickOutside)
|
||||||
.show(|ui| font_menu_body(app, ui, menu, current, field.rect.width()))
|
.show_ui_with_header(|ui| font_menu_header(app, ui, menu, current, width), font_menu_list)
|
||||||
.and_then(|r| r.inner)
|
.flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The style a pick sets: the one picked, else the family's Regular (else its first).
|
/// The style a pick sets: the one picked, else the family's Regular (else its first).
|
||||||
@@ -454,7 +462,7 @@ pub fn style_shown(current: &str) -> String {
|
|||||||
pub fn font_style_picker(app: &mut DesignApp, ui: &mut egui::Ui, family: &str, current: &str, width: f32) {
|
pub fn font_style_picker(app: &mut DesignApp, ui: &mut egui::Ui, family: &str, current: &str, width: f32) {
|
||||||
let styles = fonts(app).styles(family);
|
let styles = fonts(app).styles(family);
|
||||||
let mut pick = None;
|
let mut pick = None;
|
||||||
let combo = egui::ComboBox::from_id_salt("font_style").selected_text(style_shown(current)).width(width).show_ui(ui, |ui| {
|
let combo = craft_ui::ComboBox::from_id_salt("font_style").selected_text(style_shown(current)).width(width).show_ui(ui, |ui| {
|
||||||
for s in &styles {
|
for s in &styles {
|
||||||
if ui.selectable_label(s == current, s).clicked() {
|
if ui.selectable_label(s == current, s).clicked() {
|
||||||
pick = Some(s.clone());
|
pick = Some(s.clone());
|
||||||
@@ -472,7 +480,7 @@ pub fn para_style_picker(app: &mut DesignApp, ui: &mut egui::Ui, current: &str,
|
|||||||
let mut pick = None;
|
let mut pick = None;
|
||||||
let shown = crate::i18n::style_name(&app.ui.language, current);
|
let shown = crate::i18n::style_name(&app.ui.language, current);
|
||||||
let label = if overridden { format!("{shown}+") } else { shown.to_string() };
|
let label = if overridden { format!("{shown}+") } else { shown.to_string() };
|
||||||
let combo = egui::ComboBox::from_id_salt("para_style").selected_text(crate::rtl::widget(ui, label)).width(width).show_ui(ui, |ui| {
|
let combo = craft_ui::ComboBox::from_id_salt("para_style").selected_text(crate::rtl::widget(ui, label)).width(width).show_ui(ui, |ui| {
|
||||||
for n in names.iter().filter(|n| *n != designcraft_doc::NO_PARA_STYLE) {
|
for n in names.iter().filter(|n| *n != designcraft_doc::NO_PARA_STYLE) {
|
||||||
if ui.selectable_label(n == current, crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, n))).clicked() {
|
if ui.selectable_label(n == current, crate::rtl::widget(ui, crate::i18n::style_name(&app.ui.language, n))).clicked() {
|
||||||
pick = Some(n.clone());
|
pick = Some(n.clone());
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ pub fn stroke_fields(app: &mut DesignApp, ui: &mut Ui, id: &str, v: &Value) -> O
|
|||||||
ui.end_row();
|
ui.end_row();
|
||||||
caption(ui, tr(&lang, "Type:"));
|
caption(ui, tr(&lang, "Type:"));
|
||||||
let shown = type_label(&lang, &v["type"]);
|
let shown = type_label(&lang, &v["type"]);
|
||||||
let combo = egui::ComboBox::from_id_salt((id, "type")).selected_text(crate::rtl::widget(ui, &shown)).width(140.0).show_ui(ui, |ui| {
|
let combo = craft_ui::ComboBox::from_id_salt((id, "type")).selected_text(crate::rtl::widget(ui, &shown)).width(140.0).show_ui(ui, |ui| {
|
||||||
for kind in TYPES {
|
for kind in TYPES {
|
||||||
let text = tr(&lang, builtin(kind).label());
|
let text = tr(&lang, builtin(kind).label());
|
||||||
if ui.selectable_label(shown == text, crate::rtl::widget(ui, text)).clicked() {
|
if ui.selectable_label(shown == text, crate::rtl::widget(ui, text)).clicked() {
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ fn select_source(app: &mut DesignApp) {
|
|||||||
fn choice(ui: &mut egui::Ui, id: &str, current: &str, options: &[(&str, &str)], lang: &str, name: &str) -> Option<String> {
|
fn choice(ui: &mut egui::Ui, id: &str, current: &str, options: &[(&str, &str)], lang: &str, name: &str) -> Option<String> {
|
||||||
let label = options.iter().find(|(value, _)| *value == current).map(|(_, text)| tr(lang, text)).unwrap_or(current);
|
let label = options.iter().find(|(value, _)| *value == current).map(|(_, text)| tr(lang, text)).unwrap_or(current);
|
||||||
let mut picked = None;
|
let mut picked = None;
|
||||||
let combo = egui::ComboBox::from_id_salt(id).selected_text(label).width(ui.available_width().min(200.0)).show_ui(ui, |ui| {
|
let combo = craft_ui::ComboBox::from_id_salt(id).selected_text(label).width(ui.available_width().min(200.0)).show_ui(ui, |ui| {
|
||||||
for (value, text) in options {
|
for (value, text) in options {
|
||||||
if ui.selectable_label(*value == current, tr(lang, text)).clicked() {
|
if ui.selectable_label(*value == current, tr(lang, text)).clicked() {
|
||||||
picked = Some((*value).to_string());
|
picked = Some((*value).to_string());
|
||||||
|
|||||||
@@ -297,13 +297,41 @@ fn clock(p: &egui::Painter, r: Rect, color: Color32) {
|
|||||||
/// one. A click on a family picks it (its Regular style), on one of its styles that style; the
|
/// one. A click on a family picks it (its Regular style), on one of its styles that style; the
|
||||||
/// arrow opens a family, the star marks a favourite and ≈ shows similar fonts, all keeping the menu
|
/// arrow opens a family, the star marks a favourite and ≈ shows similar fonts, all keeping the menu
|
||||||
/// open (it closes on a click outside only).
|
/// open (it closes on a click outside only).
|
||||||
pub fn font_menu_body(app: &mut DesignApp, ui: &mut Ui, menu: &[FamilyInfo], current: &str, width: f32) -> Option<FontPick> {
|
///
|
||||||
|
/// [`font_menu_header`] lays out the search field and the filters, [`font_menu_list`] the rows
|
||||||
|
/// under them: the header and list of a [`craft_ui::combo::Menu`] or [`craft_ui::ComboBox`], so
|
||||||
|
/// only the rows scroll. Rows a field adds above the search (a blank "no font" row) go in the
|
||||||
|
/// header before [`font_menu_header`].
|
||||||
|
pub struct FontMenu<'a> {
|
||||||
|
app: &'a mut DesignApp,
|
||||||
|
menu: &'a [FamilyInfo],
|
||||||
|
current: &'a str,
|
||||||
|
st: MenuState,
|
||||||
|
rows: Vec<Row>,
|
||||||
|
highlighted_row: Option<usize>,
|
||||||
|
loading: bool,
|
||||||
|
sample: String,
|
||||||
|
row_h: f32,
|
||||||
|
sample_size: f32,
|
||||||
|
down: bool,
|
||||||
|
up: bool,
|
||||||
|
escape: bool,
|
||||||
|
pick: Option<FontPick>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The Font menu's maximum height, its search field and filters included.
|
||||||
|
pub const FONT_MENU_HEIGHT: f32 = 500.0;
|
||||||
|
|
||||||
|
const STATE_ID: &str = "font_menu_state";
|
||||||
|
|
||||||
|
/// The Font menu's search field and filters, for the header of a menu whose list is
|
||||||
|
/// [`font_menu_list`]. See [`FontMenu`].
|
||||||
|
pub fn font_menu_header<'a>(app: &'a mut DesignApp, ui: &mut Ui, menu: &'a [FamilyInfo], current: &'a str, width: f32) -> FontMenu<'a> {
|
||||||
let lang = app.ui.language.clone();
|
let lang = app.ui.language.clone();
|
||||||
let tr = |s: &'static str| crate::i18n::tr(&lang, s);
|
let tr = |s: &'static str| crate::i18n::tr(&lang, s);
|
||||||
let (fonts, scope) = (super::fonts(app), super::font_scope(app));
|
let (fonts, scope) = (super::fonts(app), super::font_scope(app));
|
||||||
let english = app.session.prefs.show_font_names_in_english;
|
let favs = app.session.prefs.favorite_fonts.clone();
|
||||||
let mut favs = app.session.prefs.favorite_fonts.clone();
|
let state_id = egui::Id::unique(STATE_ID);
|
||||||
let state_id = egui::Id::unique("font_menu_state");
|
|
||||||
let mut st: MenuState = ui.data(|d| d.get_temp(state_id)).unwrap_or_default();
|
let mut st: MenuState = ui.data(|d| d.get_temp(state_id)).unwrap_or_default();
|
||||||
let frame = ui.ctx().cumulative_frame_nr();
|
let frame = ui.ctx().cumulative_frame_nr();
|
||||||
if st.frame.is_none_or(|f| f.saturating_add(1) < frame) {
|
if st.frame.is_none_or(|f| f.saturating_add(1) < frame) {
|
||||||
@@ -315,7 +343,6 @@ pub fn font_menu_body(app: &mut DesignApp, ui: &mut Ui, menu: &[FamilyInfo], cur
|
|||||||
let t = Tokens::get(ui.ctx());
|
let t = Tokens::get(ui.ctx());
|
||||||
ui.set_width(width.max(560.0));
|
ui.set_width(width.max(560.0));
|
||||||
let mut pick: Option<FontPick> = None;
|
let mut pick: Option<FontPick> = None;
|
||||||
let mut favs_changed = false;
|
|
||||||
// The keys the menu uses are its own: a dialog under it never sees Return or Escape.
|
// The keys the menu uses are its own: a dialog under it never sees Return or Escape.
|
||||||
let (down, up, enter, escape) = ui.input_mut(|i| {
|
let (down, up, enter, escape) = ui.input_mut(|i| {
|
||||||
let mut key = |k| i.consume_key(egui::Modifiers::NONE, k);
|
let mut key = |k| i.consume_key(egui::Modifiers::NONE, k);
|
||||||
@@ -506,20 +533,23 @@ pub fn font_menu_body(app: &mut DesignApp, ui: &mut Ui, menu: &[FamilyInfo], cur
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FontMenu { app, menu, current, st, rows, highlighted_row, loading, sample, row_h, sample_size, down, up, escape, pick }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The Font menu's rows, under [`font_menu_header`]. Returns the font picked.
|
||||||
|
pub fn font_menu_list(ui: &mut Ui, m: FontMenu<'_>) -> Option<FontPick> {
|
||||||
|
let FontMenu { app, menu, current, mut st, rows, highlighted_row, loading, sample, row_h, sample_size, down, up, escape, mut pick } = m;
|
||||||
|
let lang = app.ui.language.clone();
|
||||||
|
let tr = |s: &'static str| crate::i18n::tr(&lang, s);
|
||||||
|
let (fonts, scope) = (super::fonts(app), super::font_scope(app));
|
||||||
|
let english = app.session.prefs.show_font_names_in_english;
|
||||||
|
let mut favs = app.session.prefs.favorite_fonts.clone();
|
||||||
|
let state_id = egui::Id::unique(STATE_ID);
|
||||||
|
let t = Tokens::get(ui.ctx());
|
||||||
|
let mut favs_changed = false;
|
||||||
let mut toggle_expand = None;
|
let mut toggle_expand = None;
|
||||||
let mut toggle_fav = None;
|
let mut toggle_fav = None;
|
||||||
let mut similar = None;
|
let mut similar = None;
|
||||||
// A popup only offers last frame's height: ask for the rows' own (a family just opened, a
|
|
||||||
// filter just cleared), up to the list's limit.
|
|
||||||
let list_h: f32 = rows
|
|
||||||
.iter()
|
|
||||||
.map(|r| match r {
|
|
||||||
Row::Family { .. } => row_h + ui.spacing().item_spacing.y,
|
|
||||||
Row::Style { .. } => row_h.min(30.0) + ui.spacing().item_spacing.y,
|
|
||||||
Row::Separator => 8.0,
|
|
||||||
})
|
|
||||||
.sum();
|
|
||||||
egui::ScrollArea::vertical().max_height(420.0).min_scrolled_height(list_h.clamp(24.0, 420.0)).auto_shrink([false, true]).show(ui, |ui| {
|
|
||||||
if loading {
|
if loading {
|
||||||
crate::rtl::label(ui, egui::RichText::new(tr("Loading fonts…")).color(t.text_dim));
|
crate::rtl::label(ui, egui::RichText::new(tr("Loading fonts…")).color(t.text_dim));
|
||||||
} else if rows.is_empty() {
|
} else if rows.is_empty() {
|
||||||
@@ -538,8 +568,7 @@ pub fn font_menu_body(app: &mut DesignApp, ui: &mut Ui, menu: &[FamilyInfo], cur
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let f = &family.family;
|
let f = &family.family;
|
||||||
let (r, mut resp) =
|
let (r, mut resp) = ui.allocate_exact_size(vec2(ui.available_width(), if style.is_some() { row_h.min(30.0) } else { row_h }), Sense::click());
|
||||||
ui.allocate_exact_size(vec2(ui.available_width(), if style.is_some() { row_h.min(30.0) } else { row_h }), Sense::click());
|
|
||||||
let highlighted = highlighted_row == Some(i);
|
let highlighted = highlighted_row == Some(i);
|
||||||
if highlighted && (down || up) {
|
if highlighted && (down || up) {
|
||||||
ui.scroll_to_rect(r, None);
|
ui.scroll_to_rect(r, None);
|
||||||
@@ -624,7 +653,6 @@ pub fn font_menu_body(app: &mut DesignApp, ui: &mut Ui, menu: &[FamilyInfo], cur
|
|||||||
pick = Some(FontPick { family: f.clone(), style: style.map(str::to_string) });
|
pick = Some(FontPick { family: f.clone(), style: style.map(str::to_string) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
if let Some(f) = toggle_expand
|
if let Some(f) = toggle_expand
|
||||||
&& !st.expanded.remove(&f)
|
&& !st.expanded.remove(&f)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -301,3 +301,66 @@ fn font_fields_in_panels_and_dialogs_search() {
|
|||||||
assert_eq!(h.state().app.ui.dialog.as_ref().map(|d| d.id.clone()), dialog_id, "{what}: Escape in the menu leaves the dialog open");
|
assert_eq!(h.state().app.ui.dialog.as_ref().map(|d| d.id.clone()), dialog_id, "{what}: Escape in the menu leaves the dialog open");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The font rows the open menu shows under its search field `search`: how many, and the bottom
|
||||||
|
/// of the lowest.
|
||||||
|
fn rows_shown(h: &Harness<'static, Window>, search: egui::Rect) -> (usize, f32) {
|
||||||
|
let families: Vec<String> = crate::panels::font_menu(&h.state().app).iter().map(|f| f.label(true).to_string()).collect();
|
||||||
|
let rows: Vec<egui::Rect> = h
|
||||||
|
.query_all_by(|n| n.role() == egui::accesskit::Role::Button && n.label().is_some_and(|l| families.contains(&l)))
|
||||||
|
.map(|n| n.rect())
|
||||||
|
.filter(|r| r.min.y > search.max.y)
|
||||||
|
.collect();
|
||||||
|
(rows.len(), rows.iter().map(|r| r.max.y).fold(f32::MIN, f32::max))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Opens the font menu of the field at `at`, searches for a font that doesn't exist and clears
|
||||||
|
/// the search: the menu grows back to the rows it showed, with the search field where it was.
|
||||||
|
/// The menu lists every family by its English name: the test UI has no CJK font for a system
|
||||||
|
/// CJK family's native name.
|
||||||
|
fn menu_regrows_after_a_search_with_no_matches(h: &mut Harness<'static, Window>, at: egui::Rect, what: &str) {
|
||||||
|
h.state_mut().app.session.prefs.show_font_names_in_english = true;
|
||||||
|
click_at(h, at.center());
|
||||||
|
h.run_steps(4);
|
||||||
|
let focused = |h: &Harness<'static, Window>| h.query_by(|n| n.role() == egui::accesskit::Role::TextInput && n.is_focused()).map(|n| n.rect());
|
||||||
|
let field = focused(h).unwrap_or_else(|| panic!("{what}: the menu opens with the search field focused"));
|
||||||
|
let (count, bottom) = rows_shown(h, field);
|
||||||
|
assert!(count > 1, "{what}: the menu lists the fonts: {count}");
|
||||||
|
|
||||||
|
let query = "zzqqxxnomatch";
|
||||||
|
h.event(egui::Event::Text(query.into()));
|
||||||
|
h.run_steps(4);
|
||||||
|
assert!(h.query_by_label("No fonts match").is_some(), "{what}: nothing matches");
|
||||||
|
assert_eq!(rows_shown(h, field).0, 0, "{what}: no rows while nothing matches");
|
||||||
|
|
||||||
|
for _ in query.chars() {
|
||||||
|
h.key_press(egui::Key::Backspace);
|
||||||
|
}
|
||||||
|
h.run_steps(4);
|
||||||
|
assert_eq!(search(h), "", "{what}: the search is cleared");
|
||||||
|
let again = focused(h).unwrap_or_else(|| panic!("{what}: the menu is still open"));
|
||||||
|
assert!((again.min.y - field.min.y).abs() < 0.5, "{what}: the search field stays at {}, not {}", field.min.y, again.min.y);
|
||||||
|
let (count_again, bottom_again) = rows_shown(h, again);
|
||||||
|
assert_eq!(count_again, count, "{what}: the menu shows as many rows as before the search");
|
||||||
|
assert!((bottom_again - bottom).abs() < 1.0, "{what}: the menu grows back to {bottom}, not {bottom_again}");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn the_font_field_menu_grows_back_after_a_search_with_no_matches() {
|
||||||
|
let (mut h, _) = typing();
|
||||||
|
let at = field(&h, designcraft_fonts::DEFAULT_FAMILY);
|
||||||
|
menu_regrows_after_a_search_with_no_matches(&mut h, at, "Control bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Paragraph Style Options › Basic Character Formats' Font Family combo box. The CJK style
|
||||||
|
/// fields' combo box hosts the same menu the same way.
|
||||||
|
#[test]
|
||||||
|
fn the_style_dialog_font_menu_grows_back_after_a_search_with_no_matches() {
|
||||||
|
let app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
|
||||||
|
let mut h = test_window::open(app, vec2(1440.0, 900.0));
|
||||||
|
let section = json!({"name": designcraft_doc::BASIC_PARAGRAPH, "section": "chars"});
|
||||||
|
h.state_mut().app.ui.dialog = Some(crate::dialogs::Dialog::new("paragraphStyleOptions", section));
|
||||||
|
h.run_steps(4);
|
||||||
|
let at = *fields(&h, designcraft_fonts::DEFAULT_FAMILY).first().expect("the dialog's font field is shown");
|
||||||
|
menu_regrows_after_a_search_with_no_matches(&mut h, at, "Paragraph Style Options");
|
||||||
|
}
|
||||||
@@ -38,7 +38,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
st.style = f.style.clone().or_else(|| db.styles(&f.family).into_iter().next()).unwrap_or_else(|| "Regular".into());
|
st.style = f.style.clone().or_else(|| db.styles(&f.family).into_iter().next()).unwrap_or_else(|| "Regular".into());
|
||||||
st.family = f.family;
|
st.family = f.family;
|
||||||
}
|
}
|
||||||
let combo = egui::ComboBox::from_id_salt("glyph_style").selected_text(&st.style).width(80.0).show_ui(ui, |ui| {
|
let combo = craft_ui::ComboBox::from_id_salt("glyph_style").selected_text(&st.style).width(80.0).show_ui(ui, |ui| {
|
||||||
for s in db.styles(&st.family) {
|
for s in db.styles(&st.family) {
|
||||||
if ui.selectable_label(s == st.style, &s).clicked() {
|
if ui.selectable_label(s == st.style, &s).clicked() {
|
||||||
st.style = s;
|
st.style = s;
|
||||||
|
|||||||
@@ -365,7 +365,7 @@ pub fn buttons(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
let mut pick = None;
|
let mut pick = None;
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "On Release"));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "On Release"));
|
||||||
let combo = egui::ComboBox::from_id_salt("button_action")
|
let combo = craft_ui::ComboBox::from_id_salt("button_action")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, labels.iter().find(|l| l.0 == kind).map_or("", |l| l.1))))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, labels.iter().find(|l| l.0 == kind).map_or("", |l| l.1))))
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
for (k, l) in labels {
|
for (k, l) in labels {
|
||||||
@@ -426,7 +426,7 @@ pub fn buttons(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
let cur = ff.as_ref().map(|f| f.kind);
|
let cur = ff.as_ref().map(|f| f.kind);
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Form Field"));
|
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, "Form Field"));
|
||||||
let combo = egui::ComboBox::from_id_salt("form_kind")
|
let combo = craft_ui::ComboBox::from_id_salt("form_kind")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, kinds.iter().find(|k| k.0 == cur).map_or("", |k| k.1))))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, kinds.iter().find(|k| k.0 == cur).map_or("", |k| k.1))))
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
for (k, l) in kinds {
|
for (k, l) in kinds {
|
||||||
@@ -539,7 +539,7 @@ pub fn liquid(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
crate::widgets::caption(ui, &format!("{} {}", crate::i18n::tr(&lang, "Page:"), d.page_name(page)));
|
crate::widgets::caption(ui, &format!("{} {}", crate::i18n::tr(&lang, "Page:"), d.page_name(page)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
let combo = egui::ComboBox::from_id_salt("liquid_rule")
|
let combo = craft_ui::ComboBox::from_id_salt("liquid_rule")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&lang, liquid_rule_label(pg.liquid))))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&lang, liquid_rule_label(pg.liquid))))
|
||||||
.width(190.0)
|
.width(190.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -669,7 +669,7 @@ pub fn transitions(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
use designcraft_doc::TransitionKind as K;
|
use designcraft_doc::TransitionKind as K;
|
||||||
crate::rtl::label(ui, egui::RichText::new(format!("{} {}", crate::i18n::tr(&app.ui.language, "Spread"), si + 1)).strong());
|
crate::rtl::label(ui, egui::RichText::new(format!("{} {}", crate::i18n::tr(&app.ui.language, "Spread"), si + 1)).strong());
|
||||||
let mut kind = cur.map(|c| c.kind);
|
let mut kind = cur.map(|c| c.kind);
|
||||||
let combo = egui::ComboBox::from_id_salt("transition_kind")
|
let combo = craft_ui::ComboBox::from_id_salt("transition_kind")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, kind.map_or("None", K::label))))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, kind.map_or("None", K::label))))
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
ui.selectable_value(&mut kind, None, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "None")));
|
ui.selectable_value(&mut kind, None, crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "None")));
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ pub fn stroke_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
StrokeType::Style { name } => name.clone(),
|
StrokeType::Style { name } => name.clone(),
|
||||||
k => k.label().to_string(),
|
k => k.label().to_string(),
|
||||||
};
|
};
|
||||||
let combo = egui::ComboBox::from_id_salt("stype")
|
let combo = craft_ui::ComboBox::from_id_salt("stype")
|
||||||
.selected_text(crate::rtl::widget(
|
.selected_text(crate::rtl::widget(
|
||||||
ui,
|
ui,
|
||||||
if matches!(st.kind, StrokeType::Style { .. }) { &shown } else { crate::i18n::tr(&app.ui.language, &shown) },
|
if matches!(st.kind, StrokeType::Style { .. }) { &shown } else { crate::i18n::tr(&app.ui.language, &shown) },
|
||||||
@@ -106,7 +106,7 @@ pub fn stroke_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
ui.end_row();
|
ui.end_row();
|
||||||
for (key, label, cur, flip) in [("start", "Start/End:", st.start, true), ("end", "", st.end, false)] {
|
for (key, label, cur, flip) in [("start", "Start/End:", st.start, true), ("end", "", st.end, false)] {
|
||||||
caption(ui, crate::i18n::tr(&app.ui.language, label));
|
caption(ui, crate::i18n::tr(&app.ui.language, label));
|
||||||
let combo = egui::ComboBox::from_id_salt(key)
|
let combo = craft_ui::ComboBox::from_id_salt(key)
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, cur.label())))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, cur.label())))
|
||||||
.width(140.0)
|
.width(140.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -305,7 +305,7 @@ fn wrap_combo(
|
|||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
caption(ui, crate::i18n::tr(&app.ui.language, caption_text));
|
caption(ui, crate::i18n::tr(&app.ui.language, caption_text));
|
||||||
let shown = opts.iter().chain(shown_only).find(|o| o.0 == cur).map_or(cur, |o| o.1).to_string();
|
let shown = opts.iter().chain(shown_only).find(|o| o.0 == cur).map_or(cur, |o| o.1).to_string();
|
||||||
let combo = egui::ComboBox::from_id_salt(salt)
|
let combo = craft_ui::ComboBox::from_id_salt(salt)
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, &shown)))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, &shown)))
|
||||||
.width(170.0)
|
.width(170.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
@@ -468,7 +468,7 @@ pub fn effects_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
B::Luminosity,
|
B::Luminosity,
|
||||||
];
|
];
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let combo = egui::ComboBox::from_id_salt("blend")
|
let combo = craft_ui::ComboBox::from_id_salt("blend")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, it.blend.label())))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, it.blend.label())))
|
||||||
.width(130.0)
|
.width(130.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ pub(super) fn character_section(app: &mut DesignApp, ui: &mut Ui) {
|
|||||||
egui::FontId::proportional(11.5),
|
egui::FontId::proportional(11.5),
|
||||||
t.text,
|
t.text,
|
||||||
);
|
);
|
||||||
if let Some(f) = crate::panels::font_popup(app, &resp, &menu, &fam) {
|
if let Some(f) = crate::panels::font_popup(app, ui, &resp, &menu, &fam) {
|
||||||
crate::panels::apply_font(app, &f);
|
crate::panels::apply_font(app, &f);
|
||||||
}
|
}
|
||||||
ui.add_space(1.0);
|
ui.add_space(1.0);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub fn character_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
let lang = c["language"].as_str().unwrap_or("English: USA").to_string();
|
let lang = c["language"].as_str().unwrap_or("English: USA").to_string();
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
caption(ui, crate::i18n::tr(&app.ui.language, "Language"));
|
caption(ui, crate::i18n::tr(&app.ui.language, "Language"));
|
||||||
let combo = egui::ComboBox::from_id_salt("char_language")
|
let combo = craft_ui::ComboBox::from_id_salt("char_language")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, &lang)))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, &lang)))
|
||||||
.width(170.0)
|
.width(170.0)
|
||||||
.show_ui(ui, |ui| language_menu(app, ui, &lang));
|
.show_ui(ui, |ui| language_menu(app, ui, &lang));
|
||||||
@@ -30,7 +30,7 @@ pub fn character_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
.iter()
|
.iter()
|
||||||
.find(|o| o.0 == digits)
|
.find(|o| o.0 == digits)
|
||||||
.map_or_else(|| digit_label(&app.ui.language, DIGIT_OPTIONS[0]), |o| digit_label(&app.ui.language, *o));
|
.map_or_else(|| digit_label(&app.ui.language, DIGIT_OPTIONS[0]), |o| digit_label(&app.ui.language, *o));
|
||||||
let combo = egui::ComboBox::from_id_salt("char_digits").selected_text(crate::rtl::widget(ui, cur)).width(150.0).show_ui(ui, |ui| {
|
let combo = craft_ui::ComboBox::from_id_salt("char_digits").selected_text(crate::rtl::widget(ui, cur)).width(150.0).show_ui(ui, |ui| {
|
||||||
for o in DIGIT_OPTIONS {
|
for o in DIGIT_OPTIONS {
|
||||||
if ui.selectable_label(o.0 == digits, crate::rtl::widget(ui, digit_label(&app.ui.language, o))).clicked() {
|
if ui.selectable_label(o.0 == digits, crate::rtl::widget(ui, digit_label(&app.ui.language, o))).clicked() {
|
||||||
let _ = app.run("type.char", json!({"attrs": {"digits": o.0}}));
|
let _ = app.run("type.char", json!({"attrs": {"digits": o.0}}));
|
||||||
|
|||||||
@@ -401,7 +401,7 @@ pub fn color_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
}
|
}
|
||||||
ui.label(egui::RichText::new(&name).size(11.0).color(t.text_dim));
|
ui.label(egui::RichText::new(&name).size(11.0).color(t.text_dim));
|
||||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||||
let combo = egui::ComboBox::from_id_salt("color_mode")
|
let combo = craft_ui::ComboBox::from_id_salt("color_mode")
|
||||||
.width(64.0)
|
.width(64.0)
|
||||||
.selected_text(match mode {
|
.selected_text(match mode {
|
||||||
ColorMode::Cmyk => "CMYK",
|
ColorMode::Cmyk => "CMYK",
|
||||||
@@ -741,7 +741,7 @@ pub fn gradient_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
crate::widgets::caption_w(ui, crate::i18n::tr(&lang, "Type:"), 52.0);
|
crate::widgets::caption_w(ui, crate::i18n::tr(&lang, "Type:"), 52.0);
|
||||||
let shown = if is_gradient { crate::i18n::tr(&lang, g.kind.label()) } else { "" };
|
let shown = if is_gradient { crate::i18n::tr(&lang, g.kind.label()) } else { "" };
|
||||||
let combo =
|
let combo =
|
||||||
egui::ComboBox::from_id_salt("grad_type").selected_text(crate::rtl::widget(ui, shown)).width(104.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt("grad_type").selected_text(crate::rtl::widget(ui, shown)).width(104.0).show_ui(ui, |ui| {
|
||||||
for (k, v) in [("Linear", "linear"), ("Radial", "radial")] {
|
for (k, v) in [("Linear", "linear"), ("Radial", "radial")] {
|
||||||
if ui
|
if ui
|
||||||
.selectable_label(is_gradient && g.kind.label() == k, crate::rtl::widget(ui, crate::i18n::tr(&lang, k)))
|
.selectable_label(is_gradient && g.kind.label() == k, crate::rtl::widget(ui, crate::i18n::tr(&lang, k)))
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
for (label, kind, names, cur) in [("Table Style", "table", tnames, tcur), ("Cell Style", "cell", cnames, ccur)] {
|
for (label, kind, names, cur) in [("Table Style", "table", tnames, tcur), ("Cell Style", "cell", cnames, ccur)] {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
caption(ui, crate::i18n::tr(&app.ui.language, label));
|
caption(ui, crate::i18n::tr(&app.ui.language, label));
|
||||||
let combo = egui::ComboBox::from_id_salt(("tp_style", kind)).selected_text(&cur).width(130.0).show_ui(ui, |ui| {
|
let combo = craft_ui::ComboBox::from_id_salt(("tp_style", kind)).selected_text(&cur).width(130.0).show_ui(ui, |ui| {
|
||||||
for n in &names {
|
for n in &names {
|
||||||
if ui.selectable_label(*n == cur, n).clicked() {
|
if ui.selectable_label(*n == cur, n).clicked() {
|
||||||
run(app, &format!("style.{kind}.apply"), json!({"name": n, "table": tid}));
|
run(app, &format!("style.{kind}.apply"), json!({"name": n, "table": tid}));
|
||||||
@@ -126,7 +126,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
let row = rows.get(r0).cloned().unwrap_or(Value::Null);
|
let row = rows.get(r0).cloned().unwrap_or(Value::Null);
|
||||||
let exactly = row["mode"] == "exactly";
|
let exactly = row["mode"] == "exactly";
|
||||||
caption(ui, crate::i18n::tr(&app.ui.language, "Row Height"));
|
caption(ui, crate::i18n::tr(&app.ui.language, "Row Height"));
|
||||||
let combo = egui::ComboBox::from_id_salt("tp_rowmode")
|
let combo = craft_ui::ComboBox::from_id_salt("tp_rowmode")
|
||||||
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, if exactly { "Exactly" } else { "At Least" })))
|
.selected_text(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, if exactly { "Exactly" } else { "At Least" })))
|
||||||
.width(70.0)
|
.width(70.0)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ fn text(ui: &mut Ui, d: &mut Dialog, key: &str, width: f32) {
|
|||||||
fn style_menu(ui: &mut Ui, d: &mut Dialog, key: &str) {
|
fn style_menu(ui: &mut Ui, d: &mut Dialog, key: &str) {
|
||||||
let current: NumberStyle = d.fields.get(key).and_then(|v| serde_json::from_value(v.clone()).ok()).unwrap_or_default();
|
let current: NumberStyle = d.fields.get(key).and_then(|v| serde_json::from_value(v.clone()).ok()).unwrap_or_default();
|
||||||
let shown = STYLES.iter().find(|(s, _)| *s == current).map_or(STYLES[0].1, |(_, l)| l);
|
let shown = STYLES.iter().find(|(s, _)| *s == current).map_or(STYLES[0].1, |(_, l)| l);
|
||||||
egui::ComboBox::from_id_salt(("section_style", key)).selected_text(shown).width(150.0).show_ui(ui, |ui| {
|
craft_ui::ComboBox::from_id_salt(("section_style", key)).selected_text(shown).width(150.0).show_ui(ui, |ui| {
|
||||||
for (style, label) in STYLES {
|
for (style, label) in STYLES {
|
||||||
if ui.selectable_label(style == current, label).clicked() {
|
if ui.selectable_label(style == current, label).clicked() {
|
||||||
d.fields.insert(key.into(), json!(style));
|
d.fields.insert(key.into(), json!(style));
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ fn text_controls(app: &mut DesignApp, ui: &mut Ui, in_text: bool) {
|
|||||||
let menu = panels::font_menu(app);
|
let menu = panels::font_menu(app);
|
||||||
let shown = if fam.is_empty() { "—".to_string() } else { panels::font_label(app, &menu, &fam) };
|
let shown = if fam.is_empty() { "—".to_string() } else { panels::font_label(app, &menu, &fam) };
|
||||||
let field = widgets::dropdown(ui, &shown, 150.0);
|
let field = widgets::dropdown(ui, &shown, 150.0);
|
||||||
if let Some(f) = panels::font_popup(app, &field, &menu, &fam) {
|
if let Some(f) = panels::font_popup(app, ui, &field, &menu, &fam) {
|
||||||
panels::apply_font(app, &f);
|
panels::apply_font(app, &f);
|
||||||
}
|
}
|
||||||
let styles = fonts.styles(&fam);
|
let styles = fonts.styles(&fam);
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
# Shared PDF backend
|
# Shared PDF backend
|
||||||
|
|
||||||
DesignCraft pins `craft-pdf`, patched Krilla 0.8.2 and the six Hayro reader crates (with
|
DesignCraft pins `craft-pdf`, patched Krilla 0.8.2 and the six Hayro reader crates (with
|
||||||
`hayro-cmap` and `hayro-postscript`) to craft-libs revision `b926b5c03e256c86ca10934f58d03f628810b5b7`. `craft-ui`,
|
`hayro-cmap` and `hayro-postscript`) to craft-libs revision `92d392cff132eaf53e13afff77f38b5c11b73aa0`. `craft-ui`,
|
||||||
`craft-print` and the other craft-libs crates are pinned to the same revision. The reader migration is reviewed on top of the separate writer change.
|
`craft-print` and the other craft-libs crates are pinned to the same revision. The reader migration is reviewed on top of the separate writer change.
|
||||||
|
|
||||||
## Writing
|
## Writing
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::process::Command;
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
const REPO: &str = "https://github.com/storytold/craft-libs";
|
const REPO: &str = "https://github.com/storytold/craft-libs";
|
||||||
const REV: &str = "b926b5c03e256c86ca10934f58d03f628810b5b7";
|
const REV: &str = "92d392cff132eaf53e13afff77f38b5c11b73aa0";
|
||||||
const PACKAGES: &[(&str, &str)] = &[
|
const PACKAGES: &[(&str, &str)] = &[
|
||||||
("craft-pdf", "0.1.0"),
|
("craft-pdf", "0.1.0"),
|
||||||
("krilla", "0.8.2"),
|
("krilla", "0.8.2"),
|
||||||
|
|||||||
Reference in new issue
Block a user