mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-29 20:47:32 -06:00
M7: lay out the Edit panel as Acrobat's (#2245)
* M7: the Edit tab turns on Edit text & images, as in Acrobat Entering Edit boxes every paragraph and image on the page at once, so text is editable with one click instead of first finding Edit text & images in the tool list. The floating toolbar gets an Edit text & images button while Edit is open or the tool is in use. Leaving Edit (or turning the tool off there) applies a paragraph still open in the editor, as clicking away from it does; left open, its page kept showing the paragraph's text removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * M7: parity notes for the Edit tab turning on Edit text & images Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * M7: the panel-reveal test looks for the Edit panel's own row With Edit text & images on, its name is on the floating toolbar as well as in the panel, so the label alone matched twice and no longer showed that the Tools tab was revealed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * M7: lay out the Edit panel as Acrobat's Under the Edit tab the panel is titled Edit, with Preferences and Close; Modify page is a row of icon buttons (rotate, insert, delete, extract) and Organize pages; Add content lists Text, Image, Header and footer, Watermark and Link, with the rest under More; Other options links Combine files, Redact a PDF and Prepare a form. The milestone banner and Ready chips are gone; a planned item is muted and says when it ships. Every row still comes from the catalogue. Edit text & images is on the floating toolbar. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * M7: Organize pages in the Edit panel opens the Organize workspace It ran page.organize, which showed the page grid behind the Edit panel; Acrobat replaces the panel with Organize pages' own. It now selects the Organize tool, so its panel and the grid open together. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * M7: translate the Edit panel's Less and Other options Every catalogue gets the two strings the Acrobat-style Edit panel adds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(i18n): refresh the catalogue hashes in ATTRIBUTION.toml Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * M7: no idle selection hint above Format text in the Edit panel "Shift-click to select several objects. Drag empty space to select an area." sat at the top of the Edit panel whenever Edit text & images was on, pushing Format text down; Acrobat's panel has no such line. The selection count and how to move it still show while objects are selected. Tests that read the hint as "nothing selected" check that no selection count shows instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * M7: let auto-deref find the Edit panel's buttons (clippy) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * M7: the Edit panel keeps main's Add / Update / Remove menu Main gave Header and footer, Watermark and Background a menu of Add, Update and Remove in the tool panel (#1857). This branch draws the Edit group in its own panel, so those rows ran only Add and Update / Remove were unreachable there. Both panels now share one helper for the caret and the menu. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Edit panel: Modify page buttons follow command enablement; Organize pages with no document asks for a file CodeRabbit on #2245: the four Modify page buttons were enabled from the catalogue (always Ready) while execute() refuses them on a document that forbids page assembly; they now use command_enabled. Organize pages with no document open selected a panel with no grid to show; it now runs page.organize, which asks for a file first. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: abc2cb <271337822+abc2cb@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
abc2cb
parent
b1bf1cf01f
commit
322a1b2ac0
+22
-22
@@ -7,7 +7,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Greek UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "6eee0b34db6529f26235bfc07fa1fdb9030b8e7b0b10ede271ca9242cb491919"
|
||||
sha256 = "e2ea97b4c68e13c22ef7f6f39f9a29d21af0e562005e2fdc9e7dfdf29effe0bb"
|
||||
|
||||
# ATTRIBUTION.toml: one entry per asset (AGENTS.md §1). The source of truth for provenance and licences.
|
||||
# ATTRIBUTION.md is generated from this file: `cargo xtask assets --write`. Checked by `cargo xtask assets` (part of `xtask ci`).
|
||||
@@ -30,7 +30,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Simplified Chinese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "9870c0fb9f7198155be16adee7f45d36cb9a254af90b545a3ce5b04cbbbf24d4"
|
||||
sha256 = "ac0a78f36b91c005b9543e6028b78bb44949fea1bf7991bf0791d407696cd832"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/zh-hant.tsv"
|
||||
@@ -41,7 +41,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Traditional Chinese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "fc31e40877ce115cfb7033c57dd6acabcae3725b249364387e3fe23e04d94e5e"
|
||||
sha256 = "c52b9a2aa403937e70859fe60b51719c97475c24927322d7534f5da0bdb5f420"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/cs.tsv"
|
||||
@@ -52,7 +52,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Czech UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "5de19834f293efaea68cb6b7f51a71d320391f53345f56cfebcd73dab828b665"
|
||||
sha256 = "0dcad418fa6399955adf2a8398aec307c2c73b13a37ca78ffe142e00491ef586"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/pt-br.tsv"
|
||||
@@ -63,7 +63,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Brazilian Portuguese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "cef0d22341d0722f029c6543fc846fce164331b7ad8f693a6754b7567b9d9e95"
|
||||
sha256 = "130f0256d4ba09bc9cb6a87fc973bad96d6b155703b713341f0afead9ad6b4b3"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/es.tsv"
|
||||
@@ -74,7 +74,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Spanish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "c0ca7761cbabd8096bc9af54cdf6b88b3ae0cd8210003db8b3356e2706e44fc8"
|
||||
sha256 = "d1093647d2af3d51f77a7b53f05ef1f45442128d40e696022624fbbece5bd0f0"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/fr.tsv"
|
||||
@@ -85,7 +85,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "French UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "a8afd51c3296f44b0446d6b06492b1348444b3e3c448a326ad213d18ce7af714"
|
||||
sha256 = "135d00bc60ef62f45ebee7c7fd83bc7433fd4054a04fb3901b2d2e8bdd2871c7"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/de.tsv"
|
||||
@@ -96,7 +96,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "German UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "7676a2dfaa7d66e2e9ef608d2d9de7f863557dcecbef6d94bafa981097405e6d"
|
||||
sha256 = "0cb38f42fe45831495699f81837fb0b2d5bb16b1b69153359c4376e9bc1e6e04"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/te.tsv"
|
||||
@@ -107,7 +107,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Telugu UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "9a22996c0308ea5b20ec5e328504cd83cbb560147763faaf0e6987f974844c29"
|
||||
sha256 = "ce97821a0fd6bf758e88e654f70985ed1e94c81e36f4e31ee3fc2f05ca39d99f"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/it.tsv"
|
||||
@@ -118,7 +118,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Italian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "eacc972d65a2d951e94e1a8cf944638e8328f73f6c05759de6059a425f159cd7"
|
||||
sha256 = "45567329bdb7884b0b54e5c5161e6e73452d85200945f1ba3661eab1fa35da06"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/pl.tsv"
|
||||
@@ -129,7 +129,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Polish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "dfa4aa540cc7d61fa22a27a949e6eec0f78dcc5b883d0e4e004d695e460b95aa"
|
||||
sha256 = "421ef329305624ebfc661a8d9cd82131e79ec279b8be47d4baec29a226e494d9"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/ru.tsv"
|
||||
@@ -140,7 +140,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Russian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "27e02e7bb3d378bceca76988a9dceaa68d974f57cbee962954deca6184cf62aa"
|
||||
sha256 = "97ed35e8959777a5f15b087136e53385430241e8522c7dc72a383c72dc0a27fd"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/hu.tsv"
|
||||
@@ -151,7 +151,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Hungarian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "9675edd36c5ae54d9893fd10c4325aab664941bf714c08fbfeef9134fa42056c"
|
||||
sha256 = "bc012e0dd9ad0d212a32b71bfc75a42ffcd058484aab28d173078384c9da480f"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/bg.tsv"
|
||||
@@ -162,7 +162,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Bulgarian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "ce18fc96f8516aa917e4a8bcfd290edec13a9800b3d1ee102e4b2a71b8467d2b"
|
||||
sha256 = "bd611d470f40a01b4442119f7189dabbe58b4904dbce398115399f02b2ecddaa"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/kk.tsv"
|
||||
@@ -173,7 +173,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Kazakh UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "286a1e2e051748eb4bcee3906918dc78d0704f8a37bde22dc50d3376d5e75017"
|
||||
sha256 = "1132e904bc1a2bcc8239987aa74b2fa75ca17d8eb20b5458eec7e2c075c0445a"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/ja.tsv"
|
||||
@@ -184,7 +184,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Japanese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "77593b7497c67f4a79cc31fa43fdd6eae11601dd87c079a8e666b25cdd9117ba"
|
||||
sha256 = "11dd8250c667ca49c40b827632b2d83cad93d07a9d5a5f27b5b9d657293efb6b"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/uk.tsv"
|
||||
@@ -195,7 +195,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Ukrainian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "d7d93a03f22ab380696f69b20b12104bf30e78c4440b683df63594af716894e2"
|
||||
sha256 = "6aa0788d784532fb67a0b589cecc27f727e6178221ee892c3de7fe8f75790607"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/ar.tsv"
|
||||
@@ -206,7 +206,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Arabic UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "889a0d0a9ea53ca0a818c2ba672c053c232d2cca140f8d63127353e6f36505fe"
|
||||
sha256 = "ed84a08b83035bc6f4d328b916692d40140c2748d383741d04fba6e013a76bb3"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/tr.tsv"
|
||||
@@ -217,7 +217,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Turkish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "bae8b21651ae2a69c71c91b69ba79727254dbfb078c1be312a13383332934927"
|
||||
sha256 = "1a5b3e9ad3f524e04bdb60e11f4a1424ca749a5ed4840e22abeaa97d24d235e8"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/lt.tsv"
|
||||
@@ -228,7 +228,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Lithuanian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "7fa70f68a9fa24d0b1cac05fe3aaabaeaca9750c57416124bd317a4eda806d5a"
|
||||
sha256 = "136f1e68fc4caa5e6e8fe395551bffdc9ace93bb00e2da5ba59318846494420d"
|
||||
|
||||
|
||||
[[asset]]
|
||||
@@ -3352,7 +3352,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Vietnamese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "95b5fc6d10f7bc8371688772741870448de716fa2dd9af62fdfe4e009d269b45"
|
||||
sha256 = "052ecb803601ebc547934136c936fb5527d6dc97e49cf8cfbde0aa2b1a6cb8c7"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/sl.tsv"
|
||||
@@ -3363,7 +3363,7 @@ licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Slovene UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "3ac2b113045b7e399dd6d9ddb7773e5b0874c8b43c2ba4cca5854598a2a7ba92"
|
||||
sha256 = "299c274d071478c49430d8dbc2a1979085fa4f8735324697e8ac0db3d3adce7c"
|
||||
|
||||
[[asset]]
|
||||
|
||||
|
||||
@@ -2711,3 +2711,5 @@ certificate Version الإصدار
|
||||
Make properties default جعل الخصائص افتراضية
|
||||
Pages selected الصفحات المحددة
|
||||
Page properties خصائص الصفحة
|
||||
Less أقل
|
||||
Other options خيارات أخرى
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -2397,3 +2397,5 @@ animation effects Off Изключени
|
||||
Make properties default Задаване като свойства по подразбиране
|
||||
Pages selected Избрани страници
|
||||
Page properties Свойства на страницата
|
||||
Less По-малко
|
||||
Other options Други опции
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 8 and column 16.
|
@@ -2508,3 +2508,5 @@ animation effects Off Vypnuto
|
||||
Make properties default Nastavit vlastnosti jako výchozí
|
||||
Pages selected Vybrané stránky
|
||||
Page properties Vlastnosti stránky
|
||||
Less Méně
|
||||
Other options Další možnosti
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -2435,3 +2435,5 @@ animation effects Off Aus
|
||||
Make properties default Eigenschaften als Standard festlegen
|
||||
Pages selected Ausgewählte Seiten
|
||||
Page properties Seiteneigenschaften
|
||||
Less Weniger
|
||||
Other options Weitere Optionen
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 51.
|
@@ -2440,3 +2440,5 @@ animation effects Off Ανενεργά
|
||||
Make properties default Ορισμός ιδιοτήτων ως προεπιλογή
|
||||
Pages selected Επιλεγμένες σελίδες
|
||||
Page properties Ιδιότητες σελίδας
|
||||
Less Λιγότερα
|
||||
Other options Άλλες επιλογές
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 477 and column 9.
|
@@ -2570,6 +2570,8 @@ animation effects Off Desactivados
|
||||
Make properties default Usar como propiedades predeterminadas
|
||||
Pages selected Páginas seleccionadas
|
||||
Page properties Propiedades de página
|
||||
Less Menos
|
||||
Other options Otras opciones
|
||||
|
||||
# Historical snapshot notice bar (View signed version / View revision).
|
||||
You are viewing the signed version of “{from}” (revision {rev}). It is a snapshot: changes here won't affect the original. Estás viendo la versión firmada de «{from}» (revisión {rev}). Es una instantánea: los cambios aquí no afectarán al original.
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 60.
|
@@ -2434,3 +2434,5 @@ animation effects Off Désactivés
|
||||
Make properties default Définir comme propriétés par défaut
|
||||
Pages selected Pages sélectionnées
|
||||
Page properties Propriétés de la page
|
||||
Less Moins
|
||||
Other options Autres options
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 39.
|
@@ -2433,3 +2433,5 @@ animation effects Off Ki
|
||||
Make properties default Tulajdonságok beállítása alapértelmezettként
|
||||
Pages selected Kijelölt oldalak
|
||||
Page properties Oldaltulajdonságok
|
||||
Less Kevesebb
|
||||
Other options Egyéb beállítások
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 44.
|
@@ -2646,3 +2646,5 @@ certificate Key usage Utilizzo chiave
|
||||
certificate Self-signed Autofirmato
|
||||
certificate SHA-1 digest Impronta SHA-1
|
||||
certificate SHA-256 digest Impronta SHA-256
|
||||
Less Meno
|
||||
Other options Altre opzioni
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -2434,3 +2434,5 @@ animation effects Off オフ
|
||||
Make properties default プロパティをデフォルトに設定
|
||||
Pages selected 選択したページ
|
||||
Page properties ページのプロパティ
|
||||
Less 折りたたむ
|
||||
Other options その他のオプション
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -2432,3 +2432,5 @@ animation effects Off Өшірулі
|
||||
Make properties default Қасиеттерді әдепкі ету
|
||||
Pages selected Таңдалған беттер
|
||||
Page properties Бет қасиеттері
|
||||
Less Азырақ
|
||||
Other options Басқа параметрлер
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 826 and column 9.
|
@@ -2685,3 +2685,5 @@ key Space Tarpas
|
||||
The password must have at least 6 characters. Slaptažodį turi sudaryti bent 6 simboliai.
|
||||
This file changed on disk. Reload it to see the new version; your unsaved changes will be lost. Šis failas diske pasikeitė. Įkelkite jį iš naujo, kad pamatytumėte naują versiją; neįrašyti pakeitimai bus prarasti.
|
||||
theme Appearance Išvaizda
|
||||
Less Mažiau
|
||||
Other options Kitos parinktys
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 404 and column 9.
|
@@ -2410,3 +2410,5 @@ animation effects Off Wyłączone
|
||||
Make properties default Ustaw właściwości jako domyślne
|
||||
Pages selected Zaznaczone strony
|
||||
Page properties Właściwości strony
|
||||
Less Mniej
|
||||
Other options Inne opcje
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -2448,3 +2448,5 @@ animation effects Off Desativados
|
||||
Make properties default Tornar propriedades padrão
|
||||
Pages selected Páginas selecionadas
|
||||
Page properties Propriedades da página
|
||||
Less Menos
|
||||
Other options Outras opções
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 9 and column 16.
|
@@ -2347,3 +2347,5 @@ animation effects Off Выкл
|
||||
Make properties default Сделать свойства стандартными
|
||||
Pages selected Выделенные страницы
|
||||
Page properties Свойства страницы
|
||||
Less Меньше
|
||||
Other options Другие параметры
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 9 and column 16.
|
@@ -2439,3 +2439,5 @@ animation effects Off Izklopljeni
|
||||
Make properties default Nastavi lastnosti kot privzete
|
||||
Pages selected Izbrane strani
|
||||
Page properties Lastnosti strani
|
||||
Less Manj
|
||||
Other options Druge možnosti
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 9 and column 16.
|
@@ -2343,3 +2343,5 @@ animation effects Off ఆఫ్
|
||||
Make properties default లక్షణాలను డిఫాల్ట్గా చేయి
|
||||
Pages selected ఎంచుకున్న పేజీలు
|
||||
Page properties పేజీ లక్షణాలు
|
||||
Less తక్కువ
|
||||
Other options ఇతర ఎంపికలు
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 13 and column 16.
|
@@ -2430,3 +2430,5 @@ animation effects Off Kapalı
|
||||
Make properties default Özellikleri varsayılan yap
|
||||
Pages selected Seçilen sayfalar
|
||||
Page properties Sayfa özellikleri
|
||||
Less Daha az
|
||||
Other options Diğer seçenekler
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 825 and column 9.
|
@@ -2456,3 +2456,5 @@ animation effects Off Вимкнено
|
||||
Make properties default Зробити властивості типовими
|
||||
Pages selected Вибрані сторінки
|
||||
Page properties Властивості сторінки
|
||||
Less Менше
|
||||
Other options Інші параметри
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -2683,6 +2683,8 @@ key Space Space
|
||||
Words Từ
|
||||
“{name}” changed on disk after it was opened or last saved. Saving now replaces that newer version with this one. “{name}” đã thay đổi trên đĩa sau khi được mở hoặc lưu lần cuối. Lưu lúc này sẽ thay thế phiên bản mới hơn đó bằng phiên bản này.
|
||||
@id file.word_count Đếm từ…
|
||||
Less Ít hơn
|
||||
Other options Tùy chọn khác
|
||||
|
||||
# Historical snapshot notice bar (View signed version / View revision).
|
||||
You are viewing the signed version of “{from}” (revision {rev}). It is a snapshot: changes here won't affect the original. Bạn đang xem phiên bản đã ký của “{from}” (bản sửa đổi {rev}). Đây là ảnh nhanh: các thay đổi ở đây không được áp dụng đến bản gốc.
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 491 and column 12.
|
@@ -2398,3 +2398,5 @@ animation effects Off 关
|
||||
Make properties default 将属性设为默认
|
||||
Pages selected 选定的页面
|
||||
Page properties 页面属性
|
||||
Less 收起
|
||||
Other options 其他选项
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 9 and column 16.
|
@@ -2384,3 +2384,5 @@ animation effects Off 關
|
||||
Make properties default 將內容設為預設
|
||||
Pages selected 選取的頁面
|
||||
Page properties 頁面屬性
|
||||
Less 收起
|
||||
Other options 其他選項
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 9 and column 16.
|
+174
-36
@@ -2,7 +2,7 @@
|
||||
//! right-hand panels (Comments, Bookmarks, Pages, Fields, Layers, Attachments).
|
||||
|
||||
use egui::{Align, Align2, Color32, CornerRadius, Layout, Rect, Sense, Stroke, pos2, vec2};
|
||||
use pdfcraft_engine::catalog::{self, Availability, TOOL_GROUPS, ToolGroup};
|
||||
use pdfcraft_engine::catalog::{self, Availability, TOOL_GROUPS, ToolGroup, ToolItem};
|
||||
use pdfcraft_render::{DocInfo, FieldKind, OutlineItem};
|
||||
|
||||
use crate::theme::{self, Tokens};
|
||||
@@ -144,6 +144,10 @@ fn tool_row(ui: &mut egui::Ui, t: &Tokens, g: &ToolGroup) -> egui::Response {
|
||||
}
|
||||
|
||||
fn tool_detail(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens, g: &'static ToolGroup) {
|
||||
if g.id == "edit" {
|
||||
edit_panel(app, ui, t, g);
|
||||
return;
|
||||
}
|
||||
let (back, close) = panel_header(ui, t, g.label, true);
|
||||
if back {
|
||||
app.left = LeftPanel::AllTools;
|
||||
@@ -185,20 +189,6 @@ fn tool_detail(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens, g: &'static
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
}
|
||||
// Edit a PDF shows Format text at the top while text is selected or being added.
|
||||
if g.id == "edit" {
|
||||
if app.quick_tool == crate::QuickTool::EditText {
|
||||
let count = app.active_ids().map_or(0, |(i, _)| app.views[i].objects.count());
|
||||
if count > 0 {
|
||||
ui.label(crate::i18n::trn(crate::i18n::current(), count as u64, "{n} object selected", "{n} objects selected"));
|
||||
ui.label(tl!("Drag the selection to move it. Esc clears the selection."));
|
||||
} else {
|
||||
ui.label(tl!("Shift-click to select several objects. Drag empty space to select an area."));
|
||||
}
|
||||
ui.add_space(6.0);
|
||||
}
|
||||
format_section(app, ui, t);
|
||||
}
|
||||
let mut run = None;
|
||||
// Redact a PDF has Acrobat's footer: Clear all / Redact all.
|
||||
let footer = g.id == "redact";
|
||||
@@ -238,31 +228,13 @@ fn tool_detail(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens, g: &'static
|
||||
ui.painter().rect_filled(r, CornerRadius::same(4), fill);
|
||||
ui.painter().text(r.center(), Align2::CENTER_CENTER, chip_label, font, cfg);
|
||||
let resp = theme::hand(resp).on_hover_text(format!("{} — {}", tl!(item.label), item.command));
|
||||
// An entry with further commands opens a menu; its caret goes before the chip.
|
||||
if item.actions.is_empty() {
|
||||
if resp.clicked() {
|
||||
run = Some(item.command);
|
||||
}
|
||||
} else {
|
||||
// A caret before the chip says the entry opens a menu (Add / Update / Remove).
|
||||
let c = r.left_center() - vec2(10.0, 0.0);
|
||||
ui.painter().add(egui::Shape::convex_polygon(
|
||||
vec![c + vec2(-3.5, -2.0), c + vec2(3.5, -2.0), c + vec2(0.0, 2.5)],
|
||||
fg,
|
||||
egui::Stroke::NONE,
|
||||
));
|
||||
egui::Popup::menu(&resp).show(|ui| {
|
||||
ui.set_min_width(180.0);
|
||||
for (n, id) in item.actions.iter().enumerate() {
|
||||
let Some(spec) = pdfcraft_engine::commands::command(id) else { continue };
|
||||
// Add stays usable with no document open: it asks for a file first.
|
||||
let enabled = (n == 0 && app.active.is_none()) || app.command_enabled(spec);
|
||||
let label = crate::i18n::menu_label(spec.id, spec.label);
|
||||
if ui.add_enabled(enabled, egui::Button::new(label)).clicked() {
|
||||
run = Some(spec.id);
|
||||
ui.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if let Some(cmd) = actions_menu(app, ui, &resp, item, r.left_center() - vec2(10.0, 0.0), fg) {
|
||||
run = Some(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -301,6 +273,172 @@ fn tool_detail(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens, g: &'static
|
||||
}
|
||||
}
|
||||
|
||||
/// The page operations Edit shows as a row of icon buttons, as Acrobat's Edit panel does.
|
||||
const EDIT_PAGE_BUTTONS: [&str; 4] = ["page.rotate", "page.insert", "page.delete", "page.extract"];
|
||||
/// Add content items shown before More.
|
||||
const EDIT_CONTENT_SHOWN: usize = 5;
|
||||
/// Other options: the tools Acrobat's Edit panel links to.
|
||||
const EDIT_OTHER_TOOLS: [&str; 3] = ["combine", "redact", "form"];
|
||||
|
||||
/// Edit a PDF, laid out as Acrobat's Edit panel: the title with Preferences and Close; Format text
|
||||
/// while text is being edited or added; Modify page as a row of icon buttons and Organize pages;
|
||||
/// Add content with the rarer items under More; and Other options, the neighbouring tools.
|
||||
/// Edit text & images itself is on the floating toolbar, and on from the moment Edit opens.
|
||||
/// Every item comes from the catalogue, so its label, icon and availability have one source.
|
||||
fn edit_panel(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens, g: &'static ToolGroup) {
|
||||
let items = || g.sections.iter().flat_map(|s| s.items.iter());
|
||||
let item = |command: &str| items().find(|i| i.command == command);
|
||||
let mut run = None;
|
||||
let mut tool = None;
|
||||
// Back to All tools only when Edit was opened from there; the Edit tab is its own way back.
|
||||
let from_all_tools = app.mode != crate::Mode::Edit;
|
||||
ui.horizontal(|ui| {
|
||||
if from_all_tools && icons::button(ui, "chevron-left", 26.0, false, tl!("Back to all tools")).clicked() {
|
||||
app.left = LeftPanel::AllTools;
|
||||
app.mode = crate::Mode::AllTools;
|
||||
}
|
||||
// "Edit" under the Edit tab, as Acrobat titles it; the tool's own name from All tools.
|
||||
let title = if from_all_tools { tl!(g.label) } else { tl!("Edit") };
|
||||
let title_width = (ui.available_width() - 2.0 * (26.0 + ui.spacing().item_spacing.x)).max(1.0);
|
||||
ui.add_sized([title_width, 26.0], egui::Label::new(egui::RichText::new(title).font(theme::semibold(15.5)).color(t.text)).truncate())
|
||||
.on_hover_text(title);
|
||||
if icons::button(ui, "settings", 26.0, false, tl!("Preferences")).clicked() {
|
||||
run = Some("app.preferences");
|
||||
}
|
||||
if icons::button(ui, "x", 26.0, false, tl!("Close panel")).clicked() {
|
||||
app.left_open = false;
|
||||
}
|
||||
});
|
||||
ui.add_space(2.0);
|
||||
ui.separator();
|
||||
ui.add_space(4.0);
|
||||
// Several objects selected: how many, and how to move them. Acrobat's panel has no idle hint.
|
||||
let count = app.active_ids().filter(|_| app.quick_tool == crate::QuickTool::EditText).map_or(0, |(i, _)| app.views[i].objects.count());
|
||||
if count > 0 {
|
||||
ui.label(crate::i18n::trn(crate::i18n::current(), count as u64, "{n} object selected", "{n} objects selected"));
|
||||
ui.label(tl!("Drag the selection to move it. Esc clears the selection."));
|
||||
ui.add_space(6.0);
|
||||
}
|
||||
// Format text at the top while text is selected or being added.
|
||||
format_section(app, ui, t);
|
||||
egui::ScrollArea::vertical().auto_shrink([false, false]).show(ui, |ui| {
|
||||
widgets::section_title(ui, tl!("Modify page"));
|
||||
ui.horizontal(|ui| {
|
||||
ui.spacing_mut().item_spacing.x = 6.0;
|
||||
for i in EDIT_PAGE_BUTTONS.iter().filter_map(|c| item(c)) {
|
||||
// Enabled as the command itself is: a document that forbids page assembly refuses these.
|
||||
let enabled = pdfcraft_engine::commands::command(i.command).is_some_and(|spec| app.command_enabled(spec));
|
||||
let resp = ui.add_enabled_ui(enabled, |ui| icons::button(ui, i.icon, 34.0, false, tl!(i.label))).inner;
|
||||
if resp.clicked() {
|
||||
run = Some(i.command);
|
||||
}
|
||||
}
|
||||
});
|
||||
ui.add_space(2.0);
|
||||
// Organize pages is a workspace of its own: its panel replaces this one, with the grid.
|
||||
if let Some(i) = item("page.organize")
|
||||
&& edit_row(ui, t, i.icon, tl!(i.label), i.availability).clicked()
|
||||
{
|
||||
// With no document there is no grid to open: the command asks for a file first.
|
||||
if app.active.is_some() {
|
||||
tool = Some("organize");
|
||||
} else {
|
||||
run = Some("page.organize");
|
||||
}
|
||||
}
|
||||
|
||||
widgets::section_title(ui, tl!("Add content"));
|
||||
let content: Vec<_> =
|
||||
g.sections.iter().filter(|s| s.title == "Add content").flat_map(|s| s.items.iter()).filter(|i| i.command != "edit.edit_text").collect();
|
||||
let more_id = egui::Id::new("edit_panel_more");
|
||||
let more = ui.data(|d| d.get_temp::<bool>(more_id)).unwrap_or(false);
|
||||
let shown = if more { content.len() } else { EDIT_CONTENT_SHOWN.min(content.len()) };
|
||||
for i in content.iter().take(shown) {
|
||||
let resp = edit_row(ui, t, i.icon, tl!(i.label), i.availability);
|
||||
// Header and footer, Watermark and Background open their Add / Update / Remove menu.
|
||||
if i.actions.is_empty() {
|
||||
if resp.clicked() {
|
||||
run = Some(i.command);
|
||||
}
|
||||
} else if let Some(cmd) = actions_menu(app, ui, &resp, i, resp.rect.right_center() - vec2(14.0, 0.0), t.text) {
|
||||
run = Some(cmd);
|
||||
}
|
||||
}
|
||||
if content.len() > EDIT_CONTENT_SHOWN {
|
||||
ui.add_space(4.0);
|
||||
let label = if more { tl!("Less") } else { tl!("More") };
|
||||
let resp = ui
|
||||
.add(
|
||||
egui::Label::new(egui::RichText::new(label).color(t.accent_text).font(theme::medium(13.0)))
|
||||
.selectable(false)
|
||||
.sense(Sense::click()),
|
||||
)
|
||||
.on_hover_cursor(egui::CursorIcon::PointingHand);
|
||||
if resp.clicked() {
|
||||
ui.data_mut(|d| d.insert_temp(more_id, !more));
|
||||
}
|
||||
}
|
||||
|
||||
widgets::section_title(ui, tl!("Other options"));
|
||||
for other in EDIT_OTHER_TOOLS.iter().filter_map(|id| catalog::group(id)) {
|
||||
if edit_row(ui, t, other.icon, tl!(other.label), other.availability).clicked() {
|
||||
tool = Some(other.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
if let Some(id) = tool {
|
||||
app.select_tool(id);
|
||||
}
|
||||
if let Some(cmd) = run {
|
||||
app.run_command(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
/// A tool entry with further commands (Add / Update / Remove): a caret at `caret` says it opens a
|
||||
/// menu, and each command is enabled by its own needs. Returns the command chosen.
|
||||
fn actions_menu(app: &PdfCraftApp, ui: &egui::Ui, resp: &egui::Response, item: &ToolItem, caret: egui::Pos2, color: Color32) -> Option<&'static str> {
|
||||
ui.painter().add(egui::Shape::convex_polygon(
|
||||
vec![caret + vec2(-3.5, -2.0), caret + vec2(3.5, -2.0), caret + vec2(0.0, 2.5)],
|
||||
color,
|
||||
egui::Stroke::NONE,
|
||||
));
|
||||
let mut run = None;
|
||||
egui::Popup::menu(resp).show(|ui| {
|
||||
ui.set_min_width(180.0);
|
||||
for (n, id) in item.actions.iter().enumerate() {
|
||||
let Some(spec) = pdfcraft_engine::commands::command(id) else { continue };
|
||||
// Add stays usable with no document open: it asks for a file first.
|
||||
let enabled = (n == 0 && app.active.is_none()) || app.command_enabled(spec);
|
||||
let label = crate::i18n::menu_label(spec.id, spec.label);
|
||||
if ui.add_enabled(enabled, egui::Button::new(label)).clicked() {
|
||||
run = Some(spec.id);
|
||||
ui.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
run
|
||||
}
|
||||
|
||||
/// One row of the Edit panel: a monochrome icon and the label, as Acrobat draws them. A planned
|
||||
/// item is muted and says when it ships when hovered.
|
||||
fn edit_row(ui: &mut egui::Ui, t: &Tokens, icon: &str, label: &str, availability: Availability) -> egui::Response {
|
||||
let (rect, resp) = ui.allocate_exact_size(vec2(ui.available_width(), 34.0), Sense::click());
|
||||
resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, label));
|
||||
let press = theme::Press::track(ui, &resp);
|
||||
press.wash(ui, rect, 6, false);
|
||||
let body = rect.translate(press.offset());
|
||||
let ready = availability == Availability::Ready;
|
||||
let fg = if ready { t.text } else { t.text_muted };
|
||||
icons::paint(ui, Rect::from_min_size(body.min + vec2(6.0, 8.0), vec2(18.0, 18.0)), icon, 17.0, if ready { t.text } else { t.text_faint });
|
||||
row_label(ui, label, theme::regular(13.5), fg, body.left_center() + vec2(34.0, 0.0), rect.width() - 42.0);
|
||||
let resp = theme::hand(resp);
|
||||
match availability {
|
||||
Availability::Ready => resp,
|
||||
Availability::Planned(m) => resp.on_hover_text(format!("{} {m}", tl!("Planned for milestone"))),
|
||||
Availability::Provider => resp.on_hover_text(tl!("Optional: needs an AI provider you configure")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a stamp: Dynamic, Sign Here and Standard Business stamps; click one, then click on the
|
||||
/// page to place it.
|
||||
fn stamp_palette(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens) {
|
||||
|
||||
@@ -3256,11 +3256,17 @@ fn paragraph_drag_points(h: &Harness<'static, PdfCraftApp>, text: &str, offset:
|
||||
|
||||
fn drag_paragraph(h: &mut Harness<'static, PdfCraftApp>, text: &str, offset: [f64; 2]) {
|
||||
let (from, to) = paragraph_drag_points(h, text, offset);
|
||||
h.get_by_label("Shift-click to select several objects. Drag empty space to select an area.");
|
||||
assert!(
|
||||
h.query_all_by_label_contains("object selected").next().is_none() && h.query_all_by_label_contains("objects selected").next().is_none(),
|
||||
"no objects selected"
|
||||
);
|
||||
assert!(h.state().views[0].line_editor.is_none());
|
||||
drag(h, from, to);
|
||||
assert!(h.state().views[0].line_editor.is_none(), "a body drag must not open the typing editor");
|
||||
h.get_by_label("Shift-click to select several objects. Drag empty space to select an area.");
|
||||
assert!(
|
||||
h.query_all_by_label_contains("object selected").next().is_none() && h.query_all_by_label_contains("objects selected").next().is_none(),
|
||||
"no objects selected"
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_dragged_paragraphs(actual: &[pdfcraft_engine::TextBlock], expected: &[pdfcraft_engine::TextBlock]) {
|
||||
|
||||
@@ -146,7 +146,10 @@ fn marquee_and_mixed_group_drag_move_once_and_undo_together() {
|
||||
h.key_press_modifiers(Modifiers::COMMAND, Key::Z);
|
||||
h.run_steps(4);
|
||||
assert_eq!(objects(&h), before);
|
||||
h.get_by_label("Shift-click to select several objects. Drag empty space to select an area.");
|
||||
assert!(
|
||||
h.query_all_by_label_contains("object selected").next().is_none() && h.query_all_by_label_contains("objects selected").next().is_none(),
|
||||
"no objects selected"
|
||||
);
|
||||
h.key_press_modifiers(Modifiers::COMMAND | Modifiers::SHIFT, Key::Z);
|
||||
h.run_steps(4);
|
||||
assert_eq!(objects(&h), after);
|
||||
@@ -171,7 +174,10 @@ fn modifier_clicks_extend_an_ordinary_selection_and_toggle_objects() {
|
||||
assert!(!h.state().session.get(h.state().views[0].id).unwrap().dirty);
|
||||
h.key_press(Key::Escape);
|
||||
h.run_steps(3);
|
||||
h.get_by_label("Shift-click to select several objects. Drag empty space to select an area.");
|
||||
assert!(
|
||||
h.query_all_by_label_contains("object selected").next().is_none() && h.query_all_by_label_contains("objects selected").next().is_none(),
|
||||
"no objects selected"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -221,7 +227,10 @@ fn a_document_change_invalidates_old_selection_before_the_next_drag() {
|
||||
.apply(id, Edit::AddText { page: 0, text: AddedText { text: "A new item".into(), rect: [40.0, 210.0, 150.0, 240.0], ..Default::default() } })
|
||||
.unwrap();
|
||||
h.run_steps(4);
|
||||
h.get_by_label("Shift-click to select several objects. Drag empty space to select an area.");
|
||||
assert!(
|
||||
h.query_all_by_label_contains("object selected").next().is_none() && h.query_all_by_label_contains("objects selected").next().is_none(),
|
||||
"no objects selected"
|
||||
);
|
||||
assert_eq!(objects(&h).len(), 5);
|
||||
}
|
||||
|
||||
|
||||
@@ -1425,3 +1425,38 @@ fn the_edit_tab_turns_on_edit_text_and_images() {
|
||||
h.run_steps(3);
|
||||
assert_eq!(h.state().quick_tool, QuickTool::Hand);
|
||||
}
|
||||
|
||||
/// Organize pages in the Edit panel opens the Organize workspace: its own panel and the page grid,
|
||||
/// not the grid behind the Edit panel.
|
||||
#[test]
|
||||
fn organize_pages_from_the_edit_panel_opens_its_panel() {
|
||||
use pdfcraft_ui_egui::LeftPanel;
|
||||
let mut h = harness(|app| app.open_bytes("fixture.pdf", None, FIXTURE.to_vec()).expect("fixture opens"));
|
||||
h.get_by_label("Edit").click();
|
||||
h.run_steps(3);
|
||||
assert_eq!(h.state().left, LeftPanel::Tool("edit"));
|
||||
assert!(
|
||||
h.query_by_label("Shift-click to select several objects. Drag empty space to select an area.").is_none(),
|
||||
"no idle hint above Format text, as in Acrobat"
|
||||
);
|
||||
h.get_by_label("Organize pages").click();
|
||||
h.run_steps(3);
|
||||
assert_eq!(h.state().left, LeftPanel::Tool("organize"));
|
||||
assert!(h.state().views[0].organize, "the page grid is showing");
|
||||
}
|
||||
|
||||
/// Header and footer, Watermark and Background keep their Add / Update / Remove menu in the Edit
|
||||
/// panel, as under All tools: Update and Remove wait for the document to have that kind of mark.
|
||||
#[test]
|
||||
fn the_edit_panel_keeps_the_add_update_remove_menu() {
|
||||
let mut h = harness(|app| app.open_bytes("fixture.pdf", None, FIXTURE.to_vec()).expect("fixture opens"));
|
||||
h.get_by_label("Edit").click();
|
||||
h.run_steps(3);
|
||||
h.get_by_label("Watermark").click();
|
||||
h.run_steps(3);
|
||||
assert_eq!(enabled(&h, "Add watermark…"), Some(true));
|
||||
assert_eq!(enabled(&h, "Remove watermark"), Some(false), "nothing to remove yet");
|
||||
h.get_by_label("Add watermark…").click();
|
||||
h.run_steps(3);
|
||||
assert_eq!(h.state().dialog, Some(pdfcraft_ui_egui::Dialog::Marks(pdfcraft_engine::MarkKind::Watermark)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user