mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-30 13:08:48 -06:00
617 lines
29 KiB
Rust
617 lines
29 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"]
|
|
|
|
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;
|
|
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;
|
|
/// Header & footer / watermark / background dialog types (tests and automation).
|
|
pub mod marks {
|
|
pub use crate::marks_ui::{MarksDraft, PageRange, Subset};
|
|
}
|
|
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;
|
|
mod editing;
|
|
pub mod folders_ui;
|
|
mod home;
|
|
pub mod last_session;
|
|
pub mod last_view;
|
|
mod panels;
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
mod pickers;
|
|
pub mod units;
|
|
pub use print_ui::{Handling as PrintHandling, OptionsSource, PrintDraft, PrinterSource, Which as PrintWhich, system_printers};
|
|
pub use redact_ui::{HiddenDraft, PagesDraft as RedactPagesDraft, RedactPrefs, SearchDraft as RedactSearchDraft, SearchMode as RedactSearchMode};
|
|
pub mod i18n;
|
|
pub mod portable;
|
|
mod recovery;
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
mod system_fonts;
|
|
mod tab_context;
|
|
pub mod theme;
|
|
pub mod ui_scale;
|
|
pub mod updates;
|
|
mod widgets;
|
|
pub mod window_controls;
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pub mod window_state;
|
|
|
|
#[cfg(all(test, not(target_arch = "wasm32")))]
|
|
mod open_worker_tests;
|
|
|
|
use pdfcraft_engine::{DocId, Session};
|
|
|
|
pub use canvas::{DocView, RasterMemory};
|
|
pub use editing::{CloseRequest, SaveTarget};
|
|
pub use files::{ExtractDraft, FilePurpose, FileRequest, RotateDraft, SplitDraft, SplitMode, SplitPlan};
|
|
pub use recovery::{AUTOSAVE_SECS, RecoveryMeta, RecoveryStore};
|
|
use theme::{ThemeKind, ThemePreference};
|
|
|
|
mod app;
|
|
mod hooks;
|
|
mod platform;
|
|
mod state;
|
|
mod tools;
|
|
mod workflows;
|
|
|
|
pub(crate) use app::{MAX_AUTHOR_CHARS, copy_refused, date_text_for_pdf, print_refused};
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
pub(crate) use app::same_file;
|
|
use canvas::autoscroll;
|
|
use canvas::crop;
|
|
use canvas::fling;
|
|
use canvas::image_pick;
|
|
use canvas::page_pointer;
|
|
pub use canvas::scroll_speed;
|
|
use canvas::signature_drag;
|
|
use canvas::wheel_boost;
|
|
use canvas::wheel_pager;
|
|
use canvas::zoom_snap;
|
|
use dialogs::appearance;
|
|
use dialogs::comment_props;
|
|
use dialogs::credits;
|
|
use dialogs::marks_ui;
|
|
use dialogs::pageboxes;
|
|
use dialogs::palette;
|
|
use dialogs::protect;
|
|
use dialogs::standards_ui;
|
|
use dialogs::word_count_ui;
|
|
pub use hooks::{FailedInbox, HostDirtyFn, HostSaveFn, Inbox, OsEvent, OsEventsFn};
|
|
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;
|
|
use platform::drag_pointer;
|
|
#[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(test)]
|
|
use state::CopyPage;
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
use state::OpenRequest;
|
|
pub use state::{
|
|
CustomDraft, Dialog, DuplicateDraft, LeftPanel, LinkOrigin, Mode, NumberDraft, OpenOutcome, PageClip, PasswordPrompt, PendingLink,
|
|
PendingRemoteLink, PropsTab, QuickTool, 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;
|
|
use workflows::ocr_ui;
|
|
use workflows::optimize_ui;
|
|
use workflows::print_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>,
|
|
}
|
|
|
|
pub struct PdfCraftApp {
|
|
/// Tools side and pane widths; which panes are open is `left_open` and `right`.
|
|
pub side_panels: side_panels::SidePanels,
|
|
pub session: Session,
|
|
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 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,
|
|
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,
|
|
/// 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,
|
|
/// 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 ▸ 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,
|
|
/// Point size for new Fill & Sign text and dates, kept across launches.
|
|
pub fill_text_size: f64,
|
|
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>,
|
|
// 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>,
|
|
/// 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: 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: 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>,
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
next_open_token: u64,
|
|
#[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,
|
|
pub toast: Option<(String, f64)>,
|
|
/// 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" 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 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])>,
|
|
/// 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)>,
|
|
/// 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>,
|
|
/// 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>>>,
|
|
/// Background jobs (OCR, actions, listing pinned folders) run inline instead (tests).
|
|
pub run_inline: bool,
|
|
/// 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>,
|
|
pub compare: Option<compare_ui::CompareState>,
|
|
/// The JavaScript console and the Document JavaScripts draft.
|
|
pub js_console: js_ui::JsConsole,
|
|
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>,
|
|
/// 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>,
|
|
/// 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)>,
|
|
/// 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,
|
|
/// What ⌘V reads instead of the system clipboard (tests).
|
|
pub clipboard_override: Option<create_ui::Clip>,
|
|
/// V is down as a plain key press (see [`Self::paste_key_released`]).
|
|
v_pressed: bool,
|
|
/// 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>,
|
|
/// 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>,
|
|
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…), added to the next frame's input in `logic`.
|
|
pub(crate) menu_input: Vec<egui::Event>,
|
|
/// 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 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)>,
|
|
/// Number pages dialog settings (1-based pages).
|
|
pub number_draft: NumberDraft,
|
|
pub(crate) word_count_draft: word_count_ui::Draft,
|
|
/// Protect Using Password dialog state.
|
|
pub protect_draft: protect::ProtectDraft,
|
|
/// Set Page Boxes dialog state.
|
|
pub boxes_draft: pageboxes::BoxesDraft,
|
|
/// Header & footer / watermark / background dialog state.
|
|
pub marks_draft: marks_ui::MarksDraft,
|
|
/// 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>,
|
|
/// An absolute GoToR target waiting for approval, before any target-file I/O (#1364).
|
|
pub pending_remote_link: Option<PendingRemoteLink>,
|
|
}
|