refactor(engine): move lib.rs items to {command_sets,doc_state,error,history,interaction,prefs,sanity,session,session/documents,session/edit,session/execute,session/undo}.rs

This commit is contained in:
aiongg
2026-10-26 22:01:25 +00:00
parent 4f7dd93268
commit ef991b9c8a
13 changed files with 2488 additions and 2418 deletions
+452
View File
@@ -0,0 +1,452 @@
use super::*;
/// Where new art goes (Illustrator's drawing modes, Shift+D cycles).
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum DrawMode {
#[default]
Normal,
Behind,
Inside,
}
/// Application preferences (Edit → Preferences). Every field is reachable through `prefs.get` /
/// `prefs.set {key, value}` (camelCase keys, validated against [`cmd::prefscmds::PREF_SPECS`]).
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(default, rename_all = "camelCase")]
pub struct Prefs {
// General
/// Arrow-key nudge distance (General → Keyboard Increment), points.
pub keyboard_increment: f64,
pub constrain_angle: f64,
pub corner_radius: f64,
pub disable_auto_add_delete: bool,
pub use_precise_cursors: bool,
pub show_tool_tips: bool,
pub anti_aliased_artwork: bool,
pub select_same_tint_percent: bool,
pub show_home_screen: bool,
pub use_preview_bounds: bool,
pub display_print_size: bool,
pub double_click_to_isolate: bool,
pub transform_pattern_tiles: bool,
pub scale_corners: bool,
/// Scale Strokes & Effects.
pub scale_strokes: bool,
pub zoom_with_mouse_wheel: bool,
/// A horizontal drag on a numeric field or its label steps its value (#400).
pub scrub_numeric_fields: bool,
/// A two-finger rotation on a Mac trackpad turns the view about the pointer once it reaches 5°.
pub trackpad_rotate_view: bool,
/// Offset for Paste / duplicate (Illustrator pastes to the view centre; we offset by this).
pub paste_offset: f64,
// Selection & Anchor Display
pub selection_tolerance: f64,
pub object_selection_by_path_only: bool,
pub snap_to_point_tolerance: f64,
pub ctrl_click_selects_behind: bool,
pub zoom_to_selection: bool,
pub move_locked_with_artboard: bool,
pub anchor_size: u32,
pub handle_style: String,
pub highlight_anchors_on_hover: bool,
pub show_handles_multiple_anchors: bool,
pub hide_corner_widget_above: f64,
pub pen_rubber_band: bool,
pub curvature_rubber_band: bool,
// Type
pub type_size_increment: f64,
pub tracking_increment: f64,
pub baseline_shift_increment: f64,
pub show_east_asian_options: bool,
pub show_indic_options: bool,
pub type_selection_by_path_only: bool,
pub font_names_in_english: bool,
pub auto_size_area_type: bool,
pub font_preview: bool,
pub font_preview_size: String,
pub recent_fonts_count: u32,
pub missing_glyph_protection: bool,
pub highlight_alternate_glyphs: bool,
/// Type › Highlight Substituted Fonts: on screen, text drawn in a substitute for a missing
/// font is highlighted, in every document (on by default).
pub highlight_substituted_fonts: bool,
pub placeholder_text: bool,
// Units
pub units_general: String,
pub units_stroke: String,
pub units_type: String,
pub units_asian_type: String,
/// Numbers Without Units Are Points: a number typed with no unit into a length field in picas
/// is read in points (on by default; the reference app dims it unless a unit is Picas).
pub numbers_without_units_are_points: bool,
pub identify_objects_by: String,
// Guides & Grid
pub guide_color: String,
pub guide_style: String,
pub grid_color: String,
pub grid_style: String,
pub gridline_every: f64,
pub grid_subdivisions: u32,
pub grids_in_back: bool,
pub show_pixel_grid: bool,
// Smart Guides
pub smart_guide_color: String,
pub alignment_guides: bool,
pub object_highlighting: bool,
pub transform_tools_guides: bool,
pub construction_guides: bool,
pub construction_angles: String,
pub anchor_path_labels: bool,
pub measurement_labels: bool,
pub spacing_guides: bool,
pub distance_guides: bool,
pub snapping_tolerance: f64,
pub snap_tangent: bool,
pub snap_perpendicular: bool,
// Slices
pub show_slice_numbers: bool,
pub slice_line_color: String,
// Hyphenation
pub hyphenation_language: String,
pub hyphenation_exceptions: String,
/// Type › Options › Additional Fonts Folder: a folder (read with its subfolders) whose fonts
/// are listed and used as if installed (#683); empty for none.
pub fonts_folder: String,
// Plug-ins & Scratch Disks
pub plugins_folder: String,
pub scratch_primary: String,
pub scratch_secondary: String,
// User Interface
pub ui_brightness: String,
/// User Interface › Accent Color: the colour of what is on, chosen or focused.
pub ui_accent: String,
/// User Interface › Color Scheme: "modern" (with the accent above) or "classic" (neutral
/// greys and a blue accent).
pub ui_color_scheme: String,
pub canvas_color: String,
pub auto_collapse_icon_panels: bool,
/// User Interface › Show Tool Group Labels: the toolbar's group names (Select, Shapes, Draw…);
/// off (as it ships, #1736), the tools run on from group to group with nothing between them.
pub tool_group_labels: bool,
pub open_documents_as_tabs: bool,
pub large_tabs: bool,
pub ui_scaling: f64,
pub scale_cursor_with_ui: bool,
/// UI language: `auto` (follow the system locale) or a language code such as `en`, `zh-hant`.
/// The list of languages belongs to the shell (`ui-egui` i18n); an unknown code reads as `auto`.
pub interface_language: String,
/// Windows and Linux: use the system's title bar and window buttons instead of the app bar
/// acting as the title bar (tiling window managers, desktops that draw their own decorations).
/// Read when the app starts. macOS always uses the system's.
pub system_title_bar: bool,
// Performance
pub gpu_performance: bool,
pub animated_zoom: bool,
/// Which graphics processor the desktop app asks for at startup (it takes effect after a
/// restart): `automatic`, `lowPower` (the integrated GPU on hybrid-graphics machines) or
/// `highPerformance` (the discrete one). The canvas is rasterized on the CPU and only
/// composited on the GPU, so the integrated GPU is plenty; presenting from the discrete GPU
/// through the integrated one made some hybrid laptops flicker (#306). Automatic is power
/// saving on Windows and macOS and the system's default GPU elsewhere, the one the desktop
/// runs on: a Wayland compositor may not show frames from another GPU (#502). Single-GPU
/// machines are unaffected.
pub gpu_preference: String,
pub history_states: u32,
pub real_time_drawing: bool,
/// Rasterizer worker threads; -1 = automatic.
pub render_threads: i32,
/// Linux: `automatic` opens the window on the session's display server; `x11` opens it through
/// XWayland on a Wayland session, where dropped files arrive (#1151); `x11WithPen` opens it
/// through XWayland only when a pen is attached (#2028). Read when the app starts.
pub linux_display_server: String,
// File Handling
pub background_save: bool,
pub background_export: bool,
pub autosave_recovery: bool,
pub autosave_interval: u32,
pub recovery_folder: String,
pub recovery_off_for_complex: bool,
pub recent_files_count: u32,
pub low_res_proxy_eps: bool,
pub anti_aliased_bitmaps: bool,
pub update_links: String,
// Clipboard Handling
pub copy_as_svg: bool,
pub copy_as_pdf: bool,
pub copy_aicb: bool,
pub aicb_mode: String,
pub paste_text_formatting: String,
// Appearance of Black
pub black_on_screen: String,
pub black_output: String,
// Devices
pub touch_workspace: bool,
pub touch_gestures: bool,
// Graphic Styles panel
/// Override Character Color: a graphic style applied to type replaces its characters' fill
/// and stroke with the style's fills and strokes.
pub override_char_color: bool,
// Pattern editing
/// Object → Pattern → Tile Edge Color (`#rrggbb`): the tile edge and swatch bounds in pattern
/// editing mode.
pub pattern_tile_edge_color: String,
/// Eyedropper Options (`eyedropper.setOptions`; a preference group, see
/// [`cmd::prefscmds::PREF_GROUPS`]).
pub eyedropper: EyedropperOptions,
/// Pathfinder panel › Pathfinder Options (`object.pathfinder.options`; a preference group, see
/// [`cmd::prefscmds::PREF_GROUPS`]).
pub pathfinder: PathfinderOptions,
/// Edit → Transparency Flattener Presets: the user's presets (the built-in ones aren't stored).
/// Not a `prefs.set` key or group (resetting the preferences keeps them): `flattener.presets.*`
/// edit it.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub flattener_presets: Vec<cmd::FlattenerPreset>,
/// Width profiles saved to the Stroke panel's Profile list (`stroke.widthProfile.*`). Not a
/// Preferences dialog field, so it has no [`cmd::prefscmds::PREF_SPECS`] row.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub width_profiles: Vec<vectorcraft_doc::SavedProfile>,
/// General → Use Japanese Crop Marks: the style of Create Trim Marks and Effect → Crop Marks.
pub japanese_crop_marks: bool,
/// Appearance panel → New Art Has Basic Appearance (on): new art takes one fill and stroke;
/// off, the whole appearance of the last selection (`appearance.setNewArtBasic`).
pub new_art_basic: bool,
/// The Color Themes panel's saved themes (`colorTheme.*`): a local library, not a Preferences
/// dialog field, so it has no [`cmd::prefscmds::PREF_SPECS`] row and resetting keeps it.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub color_themes: Vec<cmd::colortheme::ColorTheme>,
/// New Document → Saved: the user's document presets (`file.newPresets.save`). A local
/// library, not a Preferences dialog field: resetting the preferences keeps it.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub new_doc_presets: Vec<cmd::newdoc::DocSettings>,
/// New Document → Recent: the settings of the last documents made (newest first).
#[serde(skip_serializing_if = "Vec::is_empty")]
pub recent_new_docs: Vec<cmd::newdoc::DocSettings>,
/// Edit → PDF Presets: the user's presets (the built-in ones aren't stored). A local library,
/// not a Preferences dialog field: resetting the preferences keeps it; `pdf.preset.*` edit it.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub pdf_presets: Vec<vectorcraft_pdf::PdfPreset>,
/// File → Export for Screens: the user's batch export presets (`document.exportPresets.*`;
/// the built-in ones aren't stored). A local library, not a Preferences dialog field.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub screen_export_presets: Vec<cmd::fileio::ScreenExportPreset>,
// File Handling (continued)
/// Where Save as Template and New from Template start ("" = `Documents/VectorCraft Templates`).
pub templates_folder: String,
/// Open older native files as "<name> [Converted]" so Save asks for a new name.
pub append_converted: bool,
/// File Handling → Use Compression: native saves are gzip-compressed (`document.save
/// {compress}` overrides it).
pub use_compression: bool,
/// Save for Web: the user's presets (the built-in ones aren't stored). A local library, not a
/// Preferences dialog field: resetting the preferences keeps it; `webExport.presets.*` edit it.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub web_export_presets: Vec<cmd::webexport::WebPreset>,
/// Save for Web: the settings the dialog opens on (`webExport.settings`); none until set.
#[serde(skip_serializing_if = "Option::is_none")]
pub web_export_settings: Option<cmd::webexport::WebSettings>,
/// Edit → Print Presets: the user's presets ([Default] isn't stored). A local library, not a
/// Preferences dialog field: resetting the preferences keeps it; `print.presets.*` edit it.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub print_presets: Vec<cmd::printpresets::PrintPreset>,
/// Constrain Width and Height Proportions: the link between W and H in the Transform panel,
/// the Properties panel and the Control bar (their size fields pass `proportional` to
/// `object.setBounds`).
pub constrain_proportions: bool,
/// One Corner Radius field sets every corner of a live rectangle (off: a field per corner).
pub single_corner_radius: bool,
/// The Transform panel menu's Transform Object Only / Transform Pattern Only / Transform Both
/// (`object`, `pattern`, `both`): what the panel's fields, flips and menu flips transform
/// (they pass `objects` and `patterns` to the transform commands). `default` (and any other
/// value), until one is chosen: they pass neither, so patterns follow General › Transform
/// Pattern Tiles (`transformPatternTiles`), as before the menu acted.
pub transform_panel_patterns: String,
/// The Transform panel menu's Use Registration Point for Symbol: with one symbol instance
/// selected, the panel and the Properties panel's Transform section measure and transform it
/// from its symbol's registration point instead of the reference point.
pub use_registration_point_for_symbol: bool,
/// The tools' persistent options by store (a tool id, or a store a family shares: `liquify`
/// holds the Liquify tools' Global Brush Dimensions), see [`vectorcraft_tools::settings`]:
/// kept across tool switches and saved with the preferences. Not a Preferences dialog field:
/// resetting the preferences keeps them; `tool.setOption` edits them.
#[serde(skip_serializing_if = "std::collections::BTreeMap::is_empty")]
pub tool_settings: std::collections::BTreeMap<String, serde_json::Map<String, Value>>,
/// View → Perspective Grid presets: the user's (the built-in ones aren't stored). A local
/// library, not a Preferences dialog field: resetting the preferences keeps it;
/// `perspective.presets.*` edit it.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub perspective_presets: Vec<vectorcraft_tools::distort::perspective::GridDefinition>,
/// Blend Options set with no blend selected: what new blends start with
/// (`object.blend.options`; none: Smooth Color, Align to Page). A tool setting, not a
/// Preferences dialog field: it has no [`cmd::prefscmds::PREF_SPECS`] row and resetting the
/// preferences keeps it.
#[serde(skip_serializing_if = "Option::is_none")]
pub blend_options: Option<vectorcraft_doc::live::BlendDefaults>,
/// Perspective Grid Options (double-click the Perspective Grid tool): whether the Plane
/// Switching Widget shows and where (`perspective.widget.options`).
pub perspective_widget: vectorcraft_tools::distort::perspective::widget::WidgetOptions,
/// What names and codes in other apps' shortcut sets stand for, as the user confirmed them on
/// import (`importMatches.*`). A local library, not a Preferences dialog field: resetting the
/// preferences keeps it.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub import_matches: Vec<cmd::importmatches::ImportMatch>,
}
impl Default for Prefs {
fn default() -> Self {
let s = |v: &str| v.to_string();
Self {
keyboard_increment: 1.0,
constrain_angle: 0.0,
corner_radius: 12.0,
disable_auto_add_delete: false,
use_precise_cursors: false,
show_tool_tips: true,
anti_aliased_artwork: true,
select_same_tint_percent: false,
show_home_screen: true,
use_preview_bounds: false,
display_print_size: false,
double_click_to_isolate: true,
transform_pattern_tiles: false,
scale_corners: false,
scale_strokes: false,
zoom_with_mouse_wheel: false,
scrub_numeric_fields: true,
trackpad_rotate_view: true,
paste_offset: 10.0,
selection_tolerance: 3.0,
object_selection_by_path_only: false,
snap_to_point_tolerance: 2.0,
ctrl_click_selects_behind: true,
zoom_to_selection: true,
move_locked_with_artboard: false,
anchor_size: 3,
handle_style: s("solid"),
highlight_anchors_on_hover: true,
show_handles_multiple_anchors: true,
hide_corner_widget_above: 177.0,
pen_rubber_band: true,
curvature_rubber_band: true,
type_size_increment: 2.0,
tracking_increment: 20.0,
baseline_shift_increment: 2.0,
show_east_asian_options: false,
show_indic_options: false,
type_selection_by_path_only: false,
font_names_in_english: true,
auto_size_area_type: false,
font_preview: true,
font_preview_size: s("medium"),
recent_fonts_count: 10,
missing_glyph_protection: true,
highlight_alternate_glyphs: false,
highlight_substituted_fonts: true,
placeholder_text: true,
units_general: s("points"),
units_stroke: s("points"),
units_type: s("points"),
units_asian_type: s("points"),
numbers_without_units_are_points: true,
identify_objects_by: s("objectName"),
guide_color: s("#4affff"),
guide_style: s("lines"),
grid_color: s("#c8c8c8"),
grid_style: s("lines"),
gridline_every: 72.0,
grid_subdivisions: 8,
grids_in_back: true,
show_pixel_grid: true,
smart_guide_color: s("#ff3dfc"),
alignment_guides: true,
object_highlighting: true,
transform_tools_guides: true,
construction_guides: true,
construction_angles: s(vectorcraft_tools::guides::DEFAULT_CONSTRUCTION_ANGLES),
anchor_path_labels: true,
measurement_labels: true,
spacing_guides: true,
distance_guides: true,
snapping_tolerance: 4.0,
snap_tangent: true,
snap_perpendicular: true,
show_slice_numbers: true,
slice_line_color: s("#ff3f3f"),
hyphenation_language: s("English: USA"),
hyphenation_exceptions: String::new(),
fonts_folder: String::new(),
plugins_folder: String::new(),
scratch_primary: s("Startup"),
scratch_secondary: s("None"),
ui_brightness: s("mediumDark"),
ui_accent: s("coral"),
ui_color_scheme: s("modern"),
canvas_color: s("matchUi"),
auto_collapse_icon_panels: false,
tool_group_labels: false,
open_documents_as_tabs: true,
large_tabs: false,
ui_scaling: 1.0,
scale_cursor_with_ui: false,
interface_language: s("auto"),
system_title_bar: false,
gpu_performance: true,
animated_zoom: true,
gpu_preference: s("automatic"),
history_states: 500,
real_time_drawing: true,
render_threads: -1,
linux_display_server: s("automatic"),
background_save: true,
background_export: true,
autosave_recovery: true,
autosave_interval: 2,
recovery_folder: String::new(),
recovery_off_for_complex: false,
recent_files_count: 20,
low_res_proxy_eps: false,
anti_aliased_bitmaps: false,
update_links: s("askWhenModified"),
copy_as_svg: true,
copy_as_pdf: false,
copy_aicb: false,
aicb_mode: s("preserveAppearance"),
paste_text_formatting: s("keep"),
black_on_screen: s("accurate"),
black_output: s("accurate"),
touch_workspace: true,
touch_gestures: true,
override_char_color: true,
pattern_tile_edge_color: {
let [r, g, b] = vectorcraft_doc::LAYER_COLORS[0].1;
Color::rgb8(r, g, b).to_hex()
},
eyedropper: Default::default(),
pathfinder: Default::default(),
flattener_presets: vec![],
width_profiles: vec![],
japanese_crop_marks: false,
new_art_basic: true,
color_themes: vec![],
new_doc_presets: vec![],
recent_new_docs: vec![],
pdf_presets: vec![],
screen_export_presets: vec![],
templates_folder: String::new(),
append_converted: true,
use_compression: false,
web_export_presets: vec![],
web_export_settings: None,
print_presets: vec![],
constrain_proportions: false,
single_corner_radius: true,
transform_panel_patterns: "default".to_string(),
use_registration_point_for_symbol: false,
tool_settings: Default::default(),
perspective_presets: vec![],
blend_options: None,
perspective_widget: Default::default(),
import_matches: vec![],
}
}
}