mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-13 13:08:41 +00:00
* AcroForm: integrate persistent timesheet script workflows * AcroForm: address review caching, worker stacks and live metadata * M6: address second review of AcroForm script workflows * M6: handle top-level ASI boundaries and verify cyclic calculation results * M6: bound script workers and isolate pending completions across edits * M6: make form resets visible before subsequent script reads * M6: include calculated dependents in reset comparison baselines * M6: bound reset writeback work before native completion * M6: charge expanded reset selections and field name bytes * M6: bound string conversion bytes and charge reset widgets * M6: preserve unread defaults and bound prompt text conversion * M6: bound reset calls early and preserve calculated field identity * AcroForm: address grouped calculations, field identity and widget ownership * AcroForm: retire field instances and address native review edge cases * AcroForm: route comparison Save As and Print to the source document * M6: dispatch text widget mouse-up scripts * M6: honor fit bounds for form button icons * AcroForm: bound calculation work and preserve reset and save integrity * Harden AcroForm script requests and worker recovery * Keep form callbacks and focus consistent across edits * AcroForm: preserve reset ordering and bound edit callbacks * Fix reset appearance ordering and XFA focus after row removal * Keep XFA focus indexes and stopped reset appearances consistent * Document form script execution and reset helpers * Keep script workers bounded and reject partial callback edits * Keep form events available after a document script reaches VM limits * Keep main's first-value Simple calculation and restore the calculateNow helper test AFSimple_Calculate (JavaScript) and the native Simple calculation count each field's first value again, as #5304 landed them; summing every selection of a multiple-selection list is a separate behaviour change. Restores the document-helper calculateNow test and the AFSimple_Calculate doc comment, and adds native and JavaScript multiple-selection cases. * Patch the callback field snapshot in place instead of rebuilding it Each field callback rebuilt all field states (3,129 on the benchmark form), and the retained realm held the previous snapshot, so stamping instance tokens copied it again. The runner now keeps its last snapshot and patches only the values and flags that changed; ScriptSession::stamp_fields stamps it before dispatch, the worker copies only when a token changes, and the realm drops the job's snapshot when the job ends (field identity is checked against the cached keys instead). * An oversized job script is that script's error, not a refused edit Realm::run refused a script too long or too deep to run as an execution refusal, which made the engine reject the whole edit (setting a 300 KiB calculation script failed). As on main it is now a plain script error that keeps the value; the realm is not touched. * Read a leading #! line as a comment in the chain scan; follow main's refusal and conditional limits in tests The nesting guard from #5079 now checks brackets, prefixes and conditionals; the document worker's preflight still bounds arrow-function and right-associative chains and skips a leading #! line as the guard does. A refused script is an error, not a refused edit, so the preflight test now checks the edit goes through with the error reported. --------- Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
862 lines
42 KiB
Rust
862 lines
42 KiB
Rust
//! pdfcraft-ui-egui — the first PdfCraft shell (L7).
|
|
//!
|
|
//! Layout grammar follows plan/acrobat/02-ui-ux.md §1: tab strip, mode bar, left tool panel,
|
|
//! floating quick-action bar, document area, right panel + right rail with page navigation.
|
|
//! Everything here is presentation: documents, rendering and the tool catalogue live in
|
|
//! `pdfcraft-engine`.
|
|
|
|
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
|
// The settings object in `persist` is one `json!` literal past the default limit of 128.
|
|
#![recursion_limit = "256"]
|
|
|
|
/// PdfCraft as craft-update knows it, with its 128 px icon and accent colour: the update
|
|
/// prompt shows both, and an AppImage's menu entry gets the icon.
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pub const UPDATE_APP: craft_update::app::App = craft_update::app::App {
|
|
icon_png: Some(include_bytes!("../../../assets/app-icon/hicolor/128x128/apps/ai.storyteller.pdfcraft.png")),
|
|
accent: Some([0xb7, 0x02, 0x28]),
|
|
..craft_update::suite::PDFCRAFT
|
|
};
|
|
|
|
use crate::control::Host as _;
|
|
|
|
/// Translate an English UI string into the current language (see [`i18n`]).
|
|
macro_rules! tl {
|
|
($s:expr) => {
|
|
$crate::i18n::t($s)
|
|
};
|
|
}
|
|
|
|
/// [`tl!`] for a label whose meaning depends on where it appears ("Type" is a column and a
|
|
/// button): a catalog can translate it under `context`, otherwise the plain translation is used.
|
|
macro_rules! tl_ctx {
|
|
($context:expr, $s:expr) => {
|
|
$crate::i18n::tr_ctx($crate::i18n::current(), $context, $s)
|
|
};
|
|
}
|
|
pub mod canvas;
|
|
mod chrome;
|
|
mod image_engine;
|
|
pub use combine_grid::ThumbState as CombineThumb;
|
|
pub use combine_ui::{Columns as CombineColumns, CombineView, Lock as CombineLock, SortKey};
|
|
mod commands;
|
|
pub mod control;
|
|
mod menus;
|
|
mod properties_session;
|
|
/// Header & footer / watermark / background dialog types (tests and automation).
|
|
pub mod marks {
|
|
pub use crate::marks_ui::{MarksDraft, PageRange, Subset};
|
|
}
|
|
pub use content_ui::TextDraft;
|
|
pub use create_ui::Clip;
|
|
pub use link_ui::LinkDraft;
|
|
pub use optimize_ui::{OptimizeDraft, OptimizeTab};
|
|
pub use sign_ui::{DigitalIdEntry, SignDraft, SignGraphic, SignStep};
|
|
mod bidi;
|
|
mod dialogs;
|
|
pub use edit_text_ui::{CropMode, DragTarget, ImageDrag, ImageHandle, ImageSelection};
|
|
mod editing;
|
|
mod home;
|
|
mod hotbar;
|
|
mod panels;
|
|
pub mod panes;
|
|
pub use print_ui::{
|
|
DefaultPaperSource, Handling as PrintHandling, OptionsSource, PrintDraft, PrinterPapersSource, PrinterSetup, PrinterSource, Spooler,
|
|
TwoSidedSource, Which as PrintWhich, system_printers, system_two_sided,
|
|
};
|
|
pub use redact_ui::{HiddenDraft, PagesDraft as RedactPagesDraft, RedactPrefs, SearchDraft as RedactSearchDraft, SearchMode as RedactSearchMode};
|
|
pub mod i18n;
|
|
pub mod theme;
|
|
pub mod viewer_prefs;
|
|
mod widgets;
|
|
|
|
use pdfcraft_engine::{DocId, Session};
|
|
|
|
pub use canvas::{DocView, RasterMemory};
|
|
#[doc(hidden)]
|
|
pub use editing::download_mime_type;
|
|
|
|
/// Smallest window the shell is laid out for, in egui points (logical pixels, so the OS scale
|
|
/// factor is already applied: 480 points are 600 px at 125 % and 720 px at 150 %). 480 is half of a
|
|
/// 1440-wide screen at 150 % scaling, the tightest common half-screen split on Windows; the mode
|
|
/// bar, tab strip and notice bars adapt below the old 820 minimum (#1913).
|
|
pub const MIN_WINDOW_SIZE: [f32; 2] = [480.0, 520.0];
|
|
pub use editing::{CloseRequest, SaveTarget};
|
|
pub use files::{ExtractDraft, FilePurpose, FileRequest, RotateDraft, SplitDraft, SplitMode, SplitPlan};
|
|
pub use recovery::{AUTOSAVE_SECS, RecoveryMeta, RecoveryStore, default_dictionary_dir};
|
|
use theme::{ThemeKind, ThemePreference};
|
|
pub use workflows::ocr_verify::{OcrVerify, Phase};
|
|
|
|
mod app;
|
|
mod frame_guard;
|
|
mod hooks;
|
|
mod persist;
|
|
mod platform;
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
mod script_dialog;
|
|
mod state;
|
|
mod tools;
|
|
mod workflows;
|
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pub(crate) mod os_clipboard;
|
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pub(crate) use app::same_file;
|
|
pub(crate) use app::{MAX_AUTHOR_CHARS, copy_refused, date_text_for_pdf, print_refused};
|
|
use canvas::autoscroll;
|
|
use canvas::crop;
|
|
use canvas::fling;
|
|
use canvas::image_pick;
|
|
use canvas::page_cursor;
|
|
use canvas::page_keys;
|
|
use canvas::page_pointer;
|
|
use canvas::page_router;
|
|
pub use canvas::scroll_speed;
|
|
use canvas::signature_drag;
|
|
use canvas::wheel_boost;
|
|
use canvas::wheel_pager;
|
|
use canvas::zoom_snap;
|
|
use dialogs::appearance;
|
|
pub use dialogs::bookmark_styles_ui;
|
|
use dialogs::comment_props;
|
|
use dialogs::convert_colours_ui;
|
|
use dialogs::credits;
|
|
use dialogs::hairlines_ui;
|
|
use dialogs::marks_ui;
|
|
use dialogs::pageboxes;
|
|
use dialogs::palette;
|
|
use dialogs::printer_marks_ui;
|
|
use dialogs::protect;
|
|
use dialogs::standards_ui;
|
|
use dialogs::word_count_ui;
|
|
pub use home::folders_ui;
|
|
pub use hooks::{FailedInbox, HostDirtyFn, HostSaveFn, Inbox, OsEvent, OsEventsFn};
|
|
use menus::tab_context;
|
|
use panels::all_tools_ui;
|
|
use panels::comments_panel;
|
|
use panels::format_text_ui;
|
|
use panels::organize_panel;
|
|
use panels::page_selection_ui;
|
|
use panels::search_ui;
|
|
pub use panels::side_panels;
|
|
pub use persist::last_session;
|
|
pub use persist::last_view;
|
|
pub use persist::paper;
|
|
use persist::recovery;
|
|
pub use persist::units;
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pub use persist::window_state;
|
|
use platform::drag_pointer;
|
|
use platform::file_filter;
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pub use platform::file_watch;
|
|
#[cfg(target_os = "macos")]
|
|
use platform::macos_association;
|
|
pub use platform::motion;
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
use platform::open_worker;
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
use platform::pickers;
|
|
pub use platform::portable;
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
use platform::system_fonts;
|
|
pub use platform::ui_scale;
|
|
pub use platform::updates;
|
|
pub use platform::window_controls;
|
|
#[cfg(test)]
|
|
use state::CopyPage;
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
use state::OpenRequest;
|
|
pub use state::{
|
|
CommentClip, CustomDraft, Dialog, DuplicateDraft, LeftPanel, LinkOrigin, Mode, NumberDraft, OpenOutcome, PageClip, PagePropsDraft,
|
|
PasswordPrompt, PendingLink, PendingRemoteLink, PropsTab, QuickTool, RECENT_FILES_DEFAULT, RECENT_FILES_MAX, RecentFile, RightPanel,
|
|
UnlockPrompt,
|
|
};
|
|
use state::{DocumentCopyJob, GridFile};
|
|
pub use tools::bulk_fields;
|
|
use tools::calc_order_ui;
|
|
use tools::camera_ui;
|
|
pub use tools::comments;
|
|
use tools::content_ui;
|
|
use tools::edit_text_ui;
|
|
pub use tools::field_table_ui;
|
|
pub use tools::fill_sign;
|
|
pub use tools::forms_ui;
|
|
use tools::link_ui;
|
|
use tools::measure_ui;
|
|
use tools::object_ui;
|
|
pub use tools::prepare;
|
|
use tools::redact_ui;
|
|
use tools::sign_ui;
|
|
use tools::stamps_ui;
|
|
use tools::tags_ui;
|
|
use widgets::icon_data;
|
|
pub use widgets::icons;
|
|
use workflows::a11y_ui;
|
|
use workflows::actions_ui;
|
|
use workflows::combine_grid;
|
|
use workflows::combine_ui;
|
|
use workflows::compare_ui;
|
|
use workflows::create_ui;
|
|
use workflows::export_ui;
|
|
use workflows::files;
|
|
use workflows::js_ui;
|
|
#[cfg(target_arch = "wasm32")]
|
|
use workflows::ocr_route;
|
|
use workflows::ocr_ui;
|
|
use workflows::ocr_verify;
|
|
#[cfg(target_arch = "wasm32")]
|
|
use workflows::ocr_web;
|
|
use workflows::optimize_ui;
|
|
use workflows::print_paper;
|
|
use workflows::print_ui;
|
|
use workflows::scan_clean_ui;
|
|
use workflows::web_print;
|
|
|
|
/// Files dropped on a document's page grid or its Pages panel.
|
|
struct GridDrop {
|
|
doc: pdfcraft_engine::DocId,
|
|
/// Dropped on the Pages panel (its gap decides where they go), not the page grid.
|
|
panel: bool,
|
|
files: Vec<GridFile>,
|
|
/// When to stop waiting for the pointer (monotonic: `logic` may run without a UI pass).
|
|
deadline: web_time::Instant,
|
|
}
|
|
|
|
/// A whole-document copy reading its pages off the UI thread (in place on the web, which has no
|
|
/// threads). Dropping it (a new copy, the document closed) stops the reading.
|
|
struct DocumentCopy {
|
|
doc: DocId,
|
|
rx: std::sync::mpsc::Receiver<String>,
|
|
cancel: std::sync::Arc<std::sync::atomic::AtomicBool>,
|
|
}
|
|
|
|
impl DocumentCopy {
|
|
fn start(doc: DocId, job: DocumentCopyJob, ctx: &egui::Context) -> DocumentCopy {
|
|
let (tx, rx) = std::sync::mpsc::channel();
|
|
let cancel = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
{
|
|
let (stop, ctx) = (cancel.clone(), ctx.clone());
|
|
let spawned = std::thread::Builder::new().name("copy-document-text".into()).spawn(move || {
|
|
if let Some(text) = job.text(&stop) {
|
|
let _ = tx.send(text);
|
|
ctx.request_repaint();
|
|
}
|
|
});
|
|
if let Err(e) = spawned {
|
|
log::warn!("copying the document's text: {e}");
|
|
}
|
|
}
|
|
#[cfg(target_arch = "wasm32")]
|
|
{
|
|
let _ = ctx;
|
|
if let Some(text) = job.text(&cancel) {
|
|
let _ = tx.send(text);
|
|
}
|
|
}
|
|
DocumentCopy { doc, rx, cancel }
|
|
}
|
|
}
|
|
|
|
impl Drop for DocumentCopy {
|
|
fn drop(&mut self) {
|
|
self.cancel.store(true, std::sync::atomic::Ordering::Relaxed);
|
|
}
|
|
}
|
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
struct PendingOpen {
|
|
token: u64,
|
|
receiver: std::sync::mpsc::Receiver<open_worker::ResultMessage>,
|
|
name: String,
|
|
path: Option<String>,
|
|
stamp: Option<file_watch::Stamp>,
|
|
activate: bool,
|
|
after_open: Option<pdfcraft_render::RemoteDestination>,
|
|
recovered: Option<RecoveryMeta>,
|
|
then: Option<&'static str>,
|
|
display_override: Option<(canvas::PageLayout, bool)>,
|
|
/// A reply taken from `receiver` and kept back for later (a password prompt waiting for an
|
|
/// earlier file's password retry).
|
|
ready: Option<open_worker::ResultKind>,
|
|
}
|
|
|
|
/// A file named while the worker's queue was full: submitted once it has room.
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
struct DeferredOpen {
|
|
path: String,
|
|
after_open: Option<pdfcraft_render::RemoteDestination>,
|
|
then: Option<&'static str>,
|
|
display_override: Option<(canvas::PageLayout, bool)>,
|
|
}
|
|
|
|
/// Puts `(html, plain_text)` on a clipboard; `false` when it couldn't, and plain-text Copy is
|
|
/// used instead.
|
|
pub type HtmlClipboard = Box<dyn FnMut(&str, &str) -> bool>;
|
|
|
|
/// A named destination being looked up off the UI thread: reading a large document's name tree
|
|
/// takes a noticeable moment.
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
struct PendingDestination {
|
|
doc: DocId,
|
|
name: String,
|
|
receiver: std::sync::mpsc::Receiver<Option<(usize, pdfcraft_render::DestView)>>,
|
|
}
|
|
|
|
pub struct PdfCraftApp {
|
|
/// Split view (`panes`); which pane shows each tab is its view's.
|
|
pub panes: panes::Panes,
|
|
/// Tools side and pane widths; which panes are open is `left_open` and `right`.
|
|
pub side_panels: side_panels::SidePanels,
|
|
pub session: Session,
|
|
/// The interface language signature status captions were last drawn in.
|
|
pub(crate) status_captions_lang: Option<i18n::Lang>,
|
|
pub views: Vec<DocView>,
|
|
pub(crate) closed_tabs: Vec<String>,
|
|
/// `None` shows the Home tab.
|
|
pub active: Option<usize>,
|
|
pub mode: Mode,
|
|
/// Workspace used for newly opened PDFs; independent of PDF Initial View metadata.
|
|
pub default_mode: Mode,
|
|
/// Page display and zoom for newly opened PDFs that don't ask for their own (Preferences ▸
|
|
/// Documents and view). Continuous scrolling at fit width by default, which never snaps
|
|
/// between pages.
|
|
pub view_defaults: canvas::ViewDefaults,
|
|
/// The unit page sizes and margins are shown in (Preferences ▸ Documents and view).
|
|
pub units: units::Unit,
|
|
/// The paper Create ▸ Blank page makes (#5644): the system region's.
|
|
pub blank_paper: paper::Paper,
|
|
/// The Preferences ▸ Date format box while it's being edited, or while it holds an invalid
|
|
/// pattern (the session keeps the last valid one).
|
|
pub date_format_draft: Option<String>,
|
|
/// Explicit CLI/control mode lasts for this session and is never persisted.
|
|
mode_override: Option<Mode>,
|
|
pub left: LeftPanel,
|
|
pub left_open: bool,
|
|
pub right: Option<RightPanel>,
|
|
/// The side panel F4 reopens: the one open last.
|
|
pub(crate) last_right: RightPanel,
|
|
/// The right panel that was open when the user switched to Read mode, which starts with the
|
|
/// panes closed; leaving Read mode brings it back unless the user opened or closed a pane in
|
|
/// Read mode meanwhile.
|
|
right_before_read: Option<RightPanel>,
|
|
/// The user closed the Comments panel, so picking a comment tool leaves it closed until they
|
|
/// open it again (#225). Remembered across restarts.
|
|
pub comments_panel_closed: bool,
|
|
/// The user closed the right panel, so opening a document leaves it closed instead of
|
|
/// showing its comments or bookmarks (#1590). Remembered across restarts.
|
|
pub right_panel_closed: bool,
|
|
/// A portfolio that just opened and the name-tree key of the attachment it presents first
|
|
/// (`/Collection /D`), opened by [`Self::present_portfolios`] on the next frame while the
|
|
/// portfolio is still the active tab.
|
|
portfolio_initial: Option<(DocId, String)>,
|
|
/// The document whose tab [`Self::present_portfolios`] last saw active.
|
|
portfolio_seen: Option<DocId>,
|
|
/// Browser file reads still under way (drops, the web file picker): each file opens in front
|
|
/// when it arrives.
|
|
#[cfg(target_arch = "wasm32")]
|
|
web_reads: std::sync::Arc<std::sync::atomic::AtomicUsize>,
|
|
/// A portfolio's file list is showing in place of this panel (`None`: the panel was
|
|
/// closed), given back when its tab is left.
|
|
portfolio_panel: Option<Option<RightPanel>>,
|
|
pub quick_tool: QuickTool,
|
|
/// The tool to go back to when Space, held for a temporary Hand, is released.
|
|
space_hand: Option<QuickTool>,
|
|
/// The tool before full screen, given back on leaving it (see [`Self::apply_full_screen`]).
|
|
full_screen_tool: Option<QuickTool>,
|
|
/// Comment author, per-tool colours and widths, pin.
|
|
pub comment_prefs: comments::CommentPrefs,
|
|
pub(crate) hotbar: hotbar::Hotbar,
|
|
/// Resolved colours, including the current OS theme when following the system.
|
|
pub theme: ThemeKind,
|
|
pub theme_preference: ThemePreference,
|
|
/// The reading-colours preference (Preferences ▸ Reading colours): applied to every open
|
|
/// document, and documents open with it (Acrobat's Replace Document Colors).
|
|
pub reading_colors: pdfcraft_render::ReadingColors,
|
|
/// App-wide page decoration only; never part of a PDF edit or render request.
|
|
pub show_page_edge_shadows: bool,
|
|
/// The Linux portal is enabled only by the native host, and starts on the first System choice.
|
|
#[cfg(target_os = "linux")]
|
|
desktop_theme: Option<pdfcraft_platform::desktop_theme::DesktopTheme>,
|
|
#[cfg(target_os = "linux")]
|
|
desktop_theme_enabled: bool,
|
|
/// How far a mouse-wheel notch scrolls.
|
|
pub scroll_speed: scroll_speed::ScrollSpeed,
|
|
/// Preferences ▸ Invert middle-button drag: the middle button's pan or auto-scroll moves the
|
|
/// view the other way. Off by default.
|
|
pub invert_middle_drag: bool,
|
|
/// Preferences ▸ Animation effects: on, off, or as the system's animation setting says.
|
|
pub animation_effects: motion::AnimationEffects,
|
|
/// Whether the system asked for no animations, and how the desktop app asks it.
|
|
pub motion: motion::Motion,
|
|
/// Interface language preference: `auto` (follow the system) or a code from [`i18n::LANGUAGES`].
|
|
pub language: String,
|
|
/// Preferences ▸ Interface size as a factor, or `None` to follow [`Self::system_text_scale`].
|
|
pub ui_scale: Option<f32>,
|
|
/// The desktop's text scaling (GNOME's text scaling factor), which the desktop app reads at
|
|
/// launch. 1.0 elsewhere, so tests and screenshots don't depend on the machine.
|
|
pub system_text_scale: f32,
|
|
/// The interface size last given to egui ([`ui_scale::sync`]).
|
|
ui_scale_applied: Option<f32>,
|
|
/// Preferences: bake Fill & Sign marks into the page when saving. Off, so a normal save stays editable.
|
|
pub flatten_fill_sign_on_save: bool,
|
|
/// Ask on the first save after Fill & Sign places a signature or initials whether to lock
|
|
/// them into the page (#2149). Off once the user says not to ask again.
|
|
pub ask_to_lock_signatures: bool,
|
|
/// Documents with a Fill & Sign signature placed since their last save, asked about on
|
|
/// saving (#2149). Not part of the recovery data: a recovered document isn't asked.
|
|
pub(crate) placed_signatures: std::collections::HashSet<pdfcraft_engine::DocId>,
|
|
/// A save waiting behind [`Dialog::LockSignatures`], and its Don't ask again box.
|
|
pub(crate) pending_lock: Option<editing::PendingLock>,
|
|
/// The document whose lock question was just answered: the save that follows the answer
|
|
/// doesn't ask again. The placed-signature mark itself stays until that save succeeds, so a
|
|
/// save that fails or is cancelled asks again next time.
|
|
pub(crate) lock_answered: Option<pdfcraft_engine::DocId>,
|
|
pub(crate) lock_remember: bool,
|
|
/// Point size for new Fill & Sign text and dates, kept across launches.
|
|
pub fill_text_size: f64,
|
|
pub fill_tool: fill_sign::FillTool,
|
|
/// Colour for new Fill & Sign text and dates, kept across launches.
|
|
pub fill_text_color: [f64; 3],
|
|
/// Border around new Fill & Sign text and dates, in points (0: none), until PdfCraft quits:
|
|
/// each launch starts from [`Self::fill_text_default`].
|
|
pub fill_text_border: f64,
|
|
/// That border's own colour (`None`: the text's).
|
|
pub fill_text_border_color: Option<pdfcraft_engine::Rgb>,
|
|
/// That border's shape (an oval or a circle goes around the text).
|
|
pub fill_text_border_shape: pdfcraft_engine::BorderShape,
|
|
/// The border new Fill & Sign text starts each launch with, kept across launches: what Make
|
|
/// Current Properties Default last took from typed text (none at first).
|
|
pub fill_text_default: fill_sign::TextBorder,
|
|
pub dialog: Option<Dialog>,
|
|
/// How to ask for the latest release (the desktop app sets it; see `updates`).
|
|
pub(crate) updates: updates::Updates,
|
|
/// Lists the Print dialog's printers in the background (the desktop app sets it; see
|
|
/// [`PrinterSource`]).
|
|
pub printer_source: Option<PrinterSource>,
|
|
/// Where Properties… reads a printer's driver options: the spooler's unless a test stands in.
|
|
pub options_source: Option<OptionsSource>,
|
|
/// Where a printer's configured default paper comes from: DEVMODE / driver settings unless a test stands in.
|
|
pub default_paper_source: Option<DefaultPaperSource>,
|
|
/// Where a printer's supported paper sizes come from: driver capabilities unless a test stands in.
|
|
pub printer_papers_source: Option<PrinterPapersSource>,
|
|
/// What print jobs go to: the system spooler unless a test stands in ([`Spooler`]).
|
|
pub spooler: Option<Spooler>,
|
|
/// Reads the picked printer's two-sided support in the background (the desktop app sets it;
|
|
/// see [`TwoSidedSource`]). Without one the dialog goes by the printer list alone.
|
|
pub two_sided_source: Option<TwoSidedSource>,
|
|
// A browser has no background print work: the type is empty there.
|
|
#[cfg_attr(target_arch = "wasm32", allow(dead_code))]
|
|
pub(crate) print_tasks: print_ui::PrintTasks,
|
|
pub palette_open: bool,
|
|
pub palette_query: String,
|
|
pub all_tools_expanded: bool,
|
|
/// The All tools view fills the workspace (its sidebar's expand button).
|
|
pub all_tools_full: bool,
|
|
pub all_tools_query: String,
|
|
/// The tab that showed when the expanded All tools view opened ([`Self::shown_tab`]). Another
|
|
/// tab coming to the front (Home, a document, Combine files) puts the view away.
|
|
all_tools_tab: (Option<DocId>, bool),
|
|
pub recent: Vec<RecentFile>,
|
|
/// How many recent files to keep, 0 for no list (Preferences ▸ Documents and view, #5572).
|
|
pub recent_limit: usize,
|
|
/// Preferences: reopen the files that were open when PdfCraft last closed (#442).
|
|
pub reopen_last_session: bool,
|
|
/// Restore last view settings when reopening documents (Preferences ▸ Documents and view;
|
|
/// #1767): the page, zoom and page display a file was last shown with. On by default.
|
|
pub restore_last_view: bool,
|
|
/// How files were last shown, most recent first (see `last_view`).
|
|
pub last_views: Vec<last_view::LastView>,
|
|
/// The files open when PdfCraft last closed, read from the settings for
|
|
/// [`PdfCraftApp::reopen_last_files`].
|
|
pub last_session: last_session::LastSession,
|
|
/// Quitting closes unsaved tabs one by one: what was open when the quit began.
|
|
quit_session: Option<last_session::LastSession>,
|
|
/// Preferences: reload a document when its file changes on disk (#431).
|
|
pub reload_changed_files: bool,
|
|
/// Preferences: ask for a newer release when the desktop app starts (#5737). Off, the app
|
|
/// asks only from Help ▸ Check for updates.
|
|
pub update_check_at_start: bool,
|
|
/// Preferences: tell the user, above the pages, that a document is secured (its security
|
|
/// settings restrict changes). Off only hides that notice (#4035); kept in the settings.
|
|
pub show_secured_notice: bool,
|
|
/// Preferences: web and email addresses written as plain page text open on a click, like
|
|
/// links (#4207).
|
|
pub text_links: bool,
|
|
/// Preferences: open every document at Default zoom and Default page display, whatever
|
|
/// layout or zoom it asks for (#1618).
|
|
pub always_default_view: bool,
|
|
/// Open documents' files, watched for changes on disk.
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pub(crate) watch: file_watch::FileWatch,
|
|
/// One native worker prepares opened documents without owning app or session state.
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
open_worker: Option<open_worker::OpenWorker>,
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pending_opens: Vec<PendingOpen>,
|
|
/// Files waiting for room in the worker's bounded queue, in the order they were named.
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
deferred_opens: std::collections::VecDeque<DeferredOpen>,
|
|
/// The open retrying a closed password prompt's file with its password: replies behind it
|
|
/// wait for it.
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
password_retry: Option<u64>,
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pending_destinations: Vec<PendingDestination>,
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
next_open_token: u64,
|
|
/// Explicit CLI layout waits for flagged launch opens, never targeting restored tabs.
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
launch_layout: Option<(canvas::PageLayout, bool)>,
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
launch_display_target: Option<DocId>,
|
|
#[cfg(all(test, not(target_arch = "wasm32")))]
|
|
open_prepare_gate: Option<std::sync::Arc<open_worker::PrepareGate>>,
|
|
/// Folders pinned to Home, and what they held when last listed.
|
|
pub pinned: folders_ui::PinnedFolders,
|
|
/// The recent files restored from settings, checked off the UI thread (#5682).
|
|
recent_check: persist::recent_check::RecentCheck,
|
|
/// Tools pinned to Home, in user-defined order.
|
|
pub pinned_tools: Vec<String>,
|
|
/// Search query for the Pin a tool selection dialog.
|
|
pub pin_tool_search: String,
|
|
pub toast: Option<(String, f64)>,
|
|
/// The form script message the toast shows now, if it shows one: drawn with its title and
|
|
/// icon (#4293).
|
|
pub toast_script: Option<pdfcraft_engine::js::Message>,
|
|
/// Form script messages waiting for the toast, in the order the scripts showed them: each
|
|
/// takes the toast when the one before it is gone, so every one is seen (#4294).
|
|
pub script_messages: std::collections::VecDeque<pdfcraft_engine::js::Message>,
|
|
/// Form script messages the waiting queue had no room for, since the toast last said how many.
|
|
pub script_messages_dropped: u64,
|
|
/// The left-out count the toast is saying now ([`Self::next_script_message`]): put back to be
|
|
/// said again if another notice replaces the toast before it has been shown its time.
|
|
pub toast_dropped: u64,
|
|
/// Whether the macOS title bar is drawn by us (traffic lights over our tab strip).
|
|
pub integrated_titlebar: bool,
|
|
/// Set when the desktop leaves the window frame to the app (GNOME on Wayland): the tab strip
|
|
/// carries these window buttons and the window's edges resize it.
|
|
pub window_controls: Option<window_controls::Layout>,
|
|
/// Preferences ▸ Use system title bar: where `window_controls` is set, give the window back
|
|
/// winit's frame instead of drawing the header bar (#1001).
|
|
pub system_title_bar: bool,
|
|
/// Whether the window currently has the app's header bar (`None` until the first frame).
|
|
app_frame_shown: Option<bool>,
|
|
pub password_prompt: Option<PasswordPrompt>,
|
|
/// Copy of a whole document's text (#2639) whose pages are being read off the UI thread.
|
|
document_copy: Option<DocumentCopy>,
|
|
pub unlock_prompt: Option<UnlockPrompt>,
|
|
pub full_screen: bool,
|
|
/// Files delivered asynchronously (web drag-and-drop, web file picker).
|
|
pub inbox: Inbox,
|
|
/// The browser's startup `?file=` download. Unlike a deliberate Open or drop, a late
|
|
/// arrival opens in the background once the user has started working (#171).
|
|
pub startup_inbox: Inbox,
|
|
startup_superseded: bool,
|
|
/// Asynchronous opens that failed (web `?file=` fetches), shown as a notice.
|
|
pub failed_inbox: FailedInbox,
|
|
/// Mirrors "some document has unsaved work, or an OCR review is open" each frame, so the web page's `beforeunload` handler can read it (#812).
|
|
pub unsaved_flag: std::sync::Arc<std::sync::atomic::AtomicBool>,
|
|
/// Requests from the operating system, polled every frame (macOS Apple events).
|
|
pub os_events: Option<OsEventsFn>,
|
|
/// Save delivers to the embedding page instead of downloading (web, see [`HostSaveFn`]).
|
|
pub host_save: Option<HostSaveFn>,
|
|
/// Reports unsaved work, or an open OCR review, to the embedding page (web, see [`HostDirtyFn`]).
|
|
pub host_dirty: Option<HostDirtyFn>,
|
|
/// A pending "save changes?" question (closing a dirty tab or quitting).
|
|
pub close_request: Option<CloseRequest>,
|
|
/// The button of the "save changes?" question the keyboard has chosen; Save when it opens.
|
|
pub(crate) save_prompt_button: dialogs::PromptButton,
|
|
/// `attend_save_prompt` has seen the pending "save changes?" question. It is false again once
|
|
/// the question is answered, so the next document's question is told apart from it.
|
|
save_prompt_seen: bool,
|
|
/// The "save changes?" question asked for the user's attention and the request still stands
|
|
/// (see `attend_save_prompt`).
|
|
save_prompt_attention: bool,
|
|
/// A save waiting behind [`Dialog::OverwriteChanged`] (the web build has no files to check).
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pub pending_overwrite: Option<editing::PendingOverwrite>,
|
|
/// Save to this path instead of asking (tests and automation).
|
|
pub save_override: Option<String>,
|
|
/// Document Properties ▸ Description fields being edited: (document, Title/Author/Subject/Keywords).
|
|
pub props_draft: Option<(DocId, [String; 4])>,
|
|
/// Attachment description being edited: (document, name-tree key, description).
|
|
pub attachment_description_draft: Option<(DocId, u64, String, String, String, bool)>,
|
|
/// Document Properties ▸ Initial View (and reading options) being edited.
|
|
pub view_draft: Option<(DocId, pdfcraft_engine::InitialView)>,
|
|
/// Document Properties ▸ Custom being edited.
|
|
pub custom_draft: Option<(DocId, CustomDraft)>,
|
|
/// Original values and document revision for the editable Properties tabs.
|
|
pub(crate) props_session: Option<properties_session::Draft>,
|
|
/// Files picked asynchronously for combine / insert (web).
|
|
pub requests: files::Requests,
|
|
/// Native file pickers in flight (they never block the frame; see `pickers`).
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pickers: pickers::Pickers,
|
|
/// Pick these files instead of showing a picker (tests and automation).
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pub pick_override: Option<Vec<String>>,
|
|
/// Write exported files (split) here instead of asking (tests and automation).
|
|
pub export_dir_override: Option<String>,
|
|
/// Split dialog settings.
|
|
pub split_draft: SplitDraft,
|
|
pub extract_draft: ExtractDraft,
|
|
pub rotate_draft: RotateDraft,
|
|
/// Summarize Comments: sort order.
|
|
pub summary_sort: pdfcraft_engine::SummarySort,
|
|
/// The signing dialogs' state.
|
|
pub sign_draft: Option<SignDraft>,
|
|
/// A dynamic form's preSign step, run when signing a field began: the document and its undo
|
|
/// depth after the step. Taken back if signing ends without a signature.
|
|
pub(crate) presign: Option<(DocId, usize)>,
|
|
/// Digital ID files the user has created or added.
|
|
pub digital_ids: Vec<DigitalIdEntry>,
|
|
/// Signatures panel: expanded entries (field names).
|
|
pub sig_expanded: Vec<String>,
|
|
/// Accessibility Checker: options, the last check, and rules skipped by hand.
|
|
pub a11y_options: a11y_ui::A11yOptions,
|
|
/// Scan & OCR: the Recognize Text choices, the running job, and (tests) run it inline.
|
|
pub ocr_draft: ocr_ui::OcrDraft,
|
|
pub ocr_run: Option<ocr_ui::OcrRun>,
|
|
pub ocr_batch: Option<std::sync::Arc<std::sync::Mutex<ocr_ui::BatchProgress>>>,
|
|
/// The web build's files being read in Web Workers (progress in `ocr_batch`).
|
|
#[cfg(target_arch = "wasm32")]
|
|
ocr_web_batch: Option<ocr_web::Batch>,
|
|
/// The web build's files chosen before the text recognition models were downloaded, with
|
|
/// the settings they were chosen with: read once the models are ready.
|
|
#[cfg(target_arch = "wasm32")]
|
|
ocr_web_waiting: Option<ocr_ui::WaitingFiles>,
|
|
/// Scan & OCR ▸ Correct recognized text: the OCR Verify screen (its state, never persisted).
|
|
pub ocr_verify: ocr_verify::OcrVerify,
|
|
/// Background jobs (OCR, actions, listing pinned folders) run inline instead (tests).
|
|
pub run_inline: bool,
|
|
/// Frames in a row whose logic or drawing panicked, and whether this frame's did
|
|
/// (`frame_guard`, #3914).
|
|
panicking_frames: u32,
|
|
frame_panicked: bool,
|
|
/// The last `logic` ran without a `ui` after it yet (eframe skips `ui` while the window is
|
|
/// hidden).
|
|
logic_without_ui: bool,
|
|
/// Tests: the part of the next frame that panics on purpose.
|
|
#[cfg(test)]
|
|
panic_next: Option<frame_guard::FramePart>,
|
|
/// Action Wizard: the user's actions, the dialog state, the running action and (tests) the
|
|
/// files to use instead of a picker.
|
|
pub custom_actions: Vec<pdfcraft_engine::actions::Action>,
|
|
pub wizard: actions_ui::Wizard,
|
|
pub action_run: Option<std::sync::Arc<std::sync::Mutex<actions_ui::RunProgress>>>,
|
|
pub action_files_override: Option<Vec<String>>,
|
|
/// Standards ▸ PDF/A: level and last result.
|
|
pub pdfa: standards_ui::PdfaState,
|
|
/// Compare files: the chosen older document and the last result.
|
|
pub compare_old: Option<DocId>,
|
|
/// The Compare Files dialog's Pages field: the new file's pages to compare, empty for all.
|
|
pub compare_pages: String,
|
|
pub compare: Option<compare_ui::CompareState>,
|
|
/// The JavaScript console and the Document JavaScripts draft.
|
|
pub js_console: js_ui::JsConsole,
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pub(crate) script_pending: Option<script_dialog::Pending>,
|
|
pub doc_js: js_ui::DocJsDraft,
|
|
pub a11y: a11y_ui::A11yState,
|
|
pub(crate) tags_state: tags_ui::State,
|
|
/// Rules skipped by hand, for the document they were skipped in.
|
|
pub a11y_skipped: std::collections::HashSet<(DocId, pdfcraft_engine::a11y::Rule)>,
|
|
pub alt_draft: a11y_ui::AltDraft,
|
|
/// List the OS key store's signing identities among the digital IDs (the desktop app).
|
|
pub os_key_store_ids: bool,
|
|
pub cert_viewer: Option<sign_ui::CertViewer>,
|
|
/// The last space audit.
|
|
pub space_audit: Vec<pdfcraft_engine::optimize::SpaceUse>,
|
|
/// The document and edit generation `space_audit` was measured from.
|
|
pub(crate) space_audit_of: Option<(DocId, u64)>,
|
|
/// Combine files: the files staged so far.
|
|
pub combine_draft: Vec<combine_ui::CombineFile>,
|
|
/// The combine list's field-name conflict preview (computed once per list, never saved).
|
|
pub combine_conflicts: combine_ui::ConflictPreview,
|
|
/// The Combine files tab: whether it is open, shown, its selection and undo history.
|
|
pub combine_tab: combine_ui::CombineTab,
|
|
/// The Combine files table's column order and widths (kept in the settings).
|
|
pub combine_columns: combine_ui::Columns,
|
|
/// Combine files as thumbnails or as the table (kept in the settings).
|
|
pub combine_view: combine_ui::CombineView,
|
|
/// How large the Combine grid draws its cards (1.0 = the usual; kept in the settings). Set
|
|
/// with [`PdfCraftApp::set_combine_zoom`].
|
|
pub combine_zoom: f32,
|
|
/// How large Organize pages draws its grid, for every document (1.0 = the usual; kept in
|
|
/// the settings).
|
|
pub organize_zoom: f32,
|
|
/// The Combine grid's thumbnails: rendered off the UI thread, a few at a time.
|
|
pub(crate) combine_thumbs: combine_grid::Thumbs,
|
|
/// Images waiting for the resolution choice (released on cancel).
|
|
pub image_import: Option<create_ui::ImageImport>,
|
|
/// The custom stamp library, and the stamp being created.
|
|
pub custom_stamps: Vec<stamps_ui::CustomStamp>,
|
|
pub stamp_draft: stamps_ui::StampDraft,
|
|
/// PDF Optimizer choices.
|
|
pub optimize_draft: OptimizeDraft,
|
|
/// The running optimization (Optimize PDF ▸ Advanced optimization).
|
|
pub optimize_run: Option<optimize_ui::OptimizeRun>,
|
|
/// Scan & OCR ▸ Enhance scanned file: the dialog's choices and the running clean-up.
|
|
pub scan_clean_draft: scan_clean_ui::ScanCleanDraft,
|
|
pub scan_clean_run: Option<scan_clean_ui::ScanCleanRun>,
|
|
/// A background job's progress card (see [`widgets::progress_notice`]).
|
|
pub progress_notice: Option<widgets::ProgressNotice>,
|
|
/// Pages copied or cut in Organize Pages, ready to paste (into any document).
|
|
pub page_clipboard: Option<PageClip>,
|
|
/// Copied comments (XFDF), to paste into this or another document (M14).
|
|
pub comment_clipboard: Option<CommentClip>,
|
|
/// Objects copied together in Edit a PDF, to paste into this or another document (#5989).
|
|
pub object_clipboard: Option<pdfcraft_engine::ObjectClipboard>,
|
|
/// What copying them put on the system clipboard (see [`app::ObjectClipMark`]).
|
|
pub(crate) object_clip_mark: app::ObjectClipMark,
|
|
/// Files dropped on the page grid, waiting for the pointer to say which gap they go to.
|
|
grid_drop: Option<GridDrop>,
|
|
/// The last snapshot (width, height, RGBA); `system_clipboard` also puts it on the
|
|
/// system clipboard (tests turn that off).
|
|
pub last_snapshot: Option<(u32, u32, pdfcraft_render::Pixels)>,
|
|
/// What `last_snapshot` was taken of: (document, page, rectangle in page view points).
|
|
last_snapshot_of: Option<(DocId, usize, [f32; 4])>,
|
|
/// The last image copied with Copy Image (width, height, straight RGBA), also put on the
|
|
/// system clipboard when `system_clipboard` is on.
|
|
pub last_copied_image: Option<(u32, u32, Vec<u8>)>,
|
|
/// The last image copied in its original format (file name, bytes), also put on the
|
|
/// system clipboard as a file when `system_clipboard` is on.
|
|
pub last_copied_file: Option<(String, Vec<u8>)>,
|
|
pub system_clipboard: bool,
|
|
/// Where Copy with formatting puts its HTML and the plain alternative instead of the system
|
|
/// clipboard, when `system_clipboard` is on (tests).
|
|
pub html_clipboard_override: Option<HtmlClipboard>,
|
|
/// The system clipboard Copy with formatting writes to, kept open so that X11 goes on
|
|
/// serving the copy after the frame.
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
os_clipboard: Option<arboard::Clipboard>,
|
|
/// What ⌘V reads instead of the system clipboard (tests).
|
|
pub clipboard_override: Option<create_ui::Clip>,
|
|
/// Attach file: the file to attach instead of asking (tests, automation).
|
|
pub attach_override: Option<(String, Vec<u8>)>,
|
|
/// Duplicate Field: which field and onto which pages.
|
|
pub duplicate_draft: Option<DuplicateDraft>,
|
|
/// Page Properties: which pages, and the tab order chosen for them.
|
|
pub page_props_draft: Option<PagePropsDraft>,
|
|
/// Text field table: the table being set up, and the page it goes on.
|
|
pub field_table_draft: Option<field_table_ui::FieldTableDraft>,
|
|
/// Prepare a form ▸ Preview: fill the form instead of editing its fields.
|
|
pub form_preview: bool,
|
|
/// Where autosaves go (`None`: autosave off, e.g. on the web and in tests).
|
|
pub recovery: Option<RecoveryStore>,
|
|
/// Entries left by a previous session, offered in the Recovery dialog.
|
|
pub recoverable: Vec<RecoveryMeta>,
|
|
recovery_keys: std::collections::HashMap<DocId, String>,
|
|
/// Recovered documents whose path came from a recovery sidecar and no save has confirmed
|
|
/// yet: their first Save asks where, starting at that path, instead of writing it (#3923).
|
|
recovered_paths: std::collections::HashSet<DocId>,
|
|
last_autosave: Option<web_time::Instant>,
|
|
allow_quit: bool,
|
|
/// Shortcuts pressed while a text field had the keyboard, run on the next frame (see
|
|
/// `registry_shortcuts`).
|
|
deferred_commands: Vec<(&'static str, Option<DocId>)>,
|
|
/// The native menu bar (macOS), while it is installed; the in-window bar shows otherwise.
|
|
pub(crate) native_menu: Option<craft_menu::NativeMenu>,
|
|
/// Input a menu click stands for (⌘C, Delete…), waiting to join a pass's input (see
|
|
/// `release_menu_input`).
|
|
pub(crate) menu_input: Vec<egui::Event>,
|
|
/// Edit ▸ Paste clicks waiting to ask the platform for the clipboard (see
|
|
/// `release_menu_input`).
|
|
pub(crate) menu_pastes: usize,
|
|
/// This frame's keys as the pages see them: none while something is over them.
|
|
pub(crate) page_keys: page_keys::PageKeys,
|
|
/// The dialog seen at the last check, and a counter bumped whenever it changes (see
|
|
/// [`Self::dialog_epoch`]).
|
|
dialog_seen: Option<Dialog>,
|
|
dialog_epoch: u64,
|
|
/// The egui context, for commands that change window or theme state.
|
|
ctx: Option<egui::Context>,
|
|
/// The window's size and place kept across a minimized close (desktop).
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pub window_state: window_state::WindowState,
|
|
styled: bool,
|
|
fonts_ready: bool,
|
|
/// The CJK fallback order the installed fonts follow (see `theme::installed_font_definitions`).
|
|
fonts_cjk: theme::CjkPreference,
|
|
/// The window title last sent to the platform.
|
|
pub window_title: String,
|
|
/// The web page's title last set: the window title, but always with the file's name.
|
|
pub page_title: String,
|
|
/// The UI control channel, when enabled (`--control`; off by default).
|
|
control: Option<control::Control>,
|
|
/// A bookmark being renamed in the Bookmarks panel: (path, text so far).
|
|
pub bookmark_rename: Option<(Vec<usize>, String)>,
|
|
/// Bookmarks copied or cut in the Bookmarks panel, with their subtrees, ready to paste into
|
|
/// any document. Destinations are page indices.
|
|
pub bookmark_clipboard: Option<Vec<pdfcraft_engine::OutlineNode>>,
|
|
/// Number pages dialog settings (1-based pages).
|
|
pub number_draft: NumberDraft,
|
|
pub(crate) word_count_draft: word_count_ui::Draft,
|
|
pub printer_marks_draft: printer_marks_ui::PrinterMarksDraft,
|
|
pub convert_colours_draft: convert_colours_ui::ConvertColoursDraft,
|
|
pub hairlines_draft: hairlines_ui::HairlinesDraft,
|
|
/// Protect Using Password dialog state.
|
|
pub protect_draft: protect::ProtectDraft,
|
|
/// New bookmarks from text styles dialog state (#1693).
|
|
pub text_style_draft: bookmark_styles_ui::TextStyleDraft,
|
|
/// Set Page Boxes dialog state.
|
|
pub boxes_draft: pageboxes::BoxesDraft,
|
|
/// Header & footer / watermark / background dialog state.
|
|
pub marks_draft: marks_ui::MarksDraft,
|
|
/// The Update dialogs' preview page without the marks they replace.
|
|
pub(crate) unmarked_page: marks_ui::UnmarkedPage,
|
|
/// Export dialog settings.
|
|
pub export_draft: export_ui::ExportDraft,
|
|
/// A running export's progress.
|
|
export_status: Option<export_ui::ExportStatus>,
|
|
/// The saved Fill & Sign signature and initials (drawn or typed).
|
|
pub signature: Option<fill_sign::SavedSig>,
|
|
pub initials: Option<fill_sign::SavedSig>,
|
|
/// The Create signature / initials dialog, and its typed preview.
|
|
pub signature_draft: fill_sign::SigDraft,
|
|
pub(crate) signature_preview: Option<(fill_sign::SavedSig, egui::TextureHandle)>,
|
|
/// The Scan tab's photo, keyed by its version.
|
|
pub(crate) signature_photo: Option<(u64, egui::TextureHandle)>,
|
|
pub(crate) saved_signature_previews: [Option<(fill_sign::SavedSig, egui::TextureHandle)>; 2],
|
|
/// What visible digital signatures show on their left, and its preview in Sign as.
|
|
pub sign_graphic: sign_ui::SignGraphic,
|
|
pub(crate) sign_graphic_preview: Option<(fill_sign::SavedSig, egui::TextureHandle)>,
|
|
#[cfg(target_arch = "wasm32")]
|
|
pub(crate) signature_images: fill_sign::ImageInbox,
|
|
/// The Comment Properties dialog's state.
|
|
pub comment_props: Option<comment_props::PropsDraft>,
|
|
pub field_props: Option<prepare::FieldDraft>,
|
|
pub bulk_field_props: Option<bulk_fields::Draft>,
|
|
pub redact_prefs: RedactPrefs,
|
|
/// The Redaction Tool Properties kept for the next run (what the last OK with "Make
|
|
/// properties default" ticked left), and the values before the dialog opened, for Cancel.
|
|
pub redact_defaults: RedactPrefs,
|
|
pub redact_before: Option<RedactPrefs>,
|
|
pub redact_pages_draft: RedactPagesDraft,
|
|
pub redact_search: RedactSearchDraft,
|
|
pub hidden_draft: HiddenDraft,
|
|
pub print_draft: PrintDraft,
|
|
pub link_draft: Option<LinkDraft>,
|
|
/// The style new text gets (Edit a PDF ▸ Format text).
|
|
pub text_style: pdfcraft_engine::AddedText,
|
|
/// The Replace Pages dialog's state.
|
|
pub replace_draft: Option<files::ReplaceDraft>,
|
|
/// The last web link the app asked the system to open (tests and automation).
|
|
pub last_opened_url: Option<String>,
|
|
/// The home screen's community card was closed; it comes back next launch (not remembered).
|
|
pub community_card_closed: bool,
|
|
/// A document asked to open this address; the user hasn't answered yet (#90, #91).
|
|
pub pending_link: Option<PendingLink>,
|
|
/// A document just opened asks to be shown in Full Screen mode (`/PageMode /FullScreen`):
|
|
/// the person is asked first, as in Acrobat, and this is the document waiting for the answer.
|
|
pub pending_full_screen: Option<DocId>,
|
|
/// A document just opened asks for its window to fit its first page or to be centred
|
|
/// (`FitWindow`, `CenterWindow`): done once the page is laid out.
|
|
pub pending_window: Option<viewer_prefs::PendingWindow>,
|
|
/// An absolute GoToR target waiting for approval, before any target-file I/O (#1364).
|
|
pub pending_remote_link: Option<PendingRemoteLink>,
|
|
}
|