forked from 1b-agent/opencadstudio-upstream
Merge branch 'main' into feature/parametric-constraint-system
# Conflicts: # src/app/automation.rs # src/app/mod.rs # src/ui/ribbon/widgets.rs
This commit is contained in:
commit
e2d39b049d
114 files changed
+13641
-1685
No files matched your search
+73
-60
@@ -9,21 +9,22 @@ pub(crate) mod config;
|
||||
pub use automation::{export_headless, serve};
|
||||
mod command_driver;
|
||||
pub(crate) mod commands;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod doc_api;
|
||||
mod document;
|
||||
pub(crate) mod expr_eval;
|
||||
mod find_replace;
|
||||
pub(crate) mod helpers;
|
||||
mod history;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod doc_api;
|
||||
mod layers;
|
||||
mod model_ops;
|
||||
mod mtext_editor;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod plugin_host;
|
||||
mod properties;
|
||||
mod presspull_ops;
|
||||
mod properties;
|
||||
mod recent;
|
||||
mod record_api;
|
||||
pub(crate) mod settings;
|
||||
mod shortcuts;
|
||||
mod startup;
|
||||
@@ -225,7 +226,10 @@ impl From<&QSelectState> for QSelectSettings {
|
||||
Self {
|
||||
scope: state.scope,
|
||||
type_filter: state.type_filter.clone(),
|
||||
property_field: state.property.as_ref().map(|property| property.field.clone()),
|
||||
property_field: state
|
||||
.property
|
||||
.as_ref()
|
||||
.map(|property| property.field.clone()),
|
||||
operator: state.operator,
|
||||
value: state.value.clone(),
|
||||
mode: state.mode,
|
||||
@@ -256,12 +260,12 @@ pub(crate) enum FindMatchKey {
|
||||
}
|
||||
use crate::snap::Snapper;
|
||||
use crate::ui::{CommandLine, Ribbon, StatusBar};
|
||||
use acadrust::types::{Color as AcadColor, LineWeight};
|
||||
use acadrust::CadDocument;
|
||||
use acadrust::types::{Color as AcadColor, LineWeight};
|
||||
|
||||
use iced::time::Instant;
|
||||
use iced::window;
|
||||
use iced::{mouse, Point, Task, Theme};
|
||||
use iced::{Point, Task, Theme, mouse};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub(super) const POLY_START_DELAY_MS: u128 = 150;
|
||||
@@ -318,9 +322,7 @@ struct AddSelectedRestore {
|
||||
}
|
||||
|
||||
/// Which Start-page section a narrow (tabbed) Start page is showing.
|
||||
#[derive(
|
||||
Clone, Copy, PartialEq, Eq, Default, Debug, serde::Serialize, serde::Deserialize,
|
||||
)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Default, Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub enum StartSection {
|
||||
Recent,
|
||||
Videos,
|
||||
@@ -780,15 +782,13 @@ pub(super) struct OpenCADStudio {
|
||||
/// Live filter for installed and available plugin cards.
|
||||
plugin_search_input: String,
|
||||
/// Installable release tags fetched per linked repo (for the dropdown).
|
||||
repo_release_tags:
|
||||
rustc_hash::FxHashMap<String, Vec<crate::plugin::external::ReleaseInfo>>,
|
||||
repo_release_tags: rustc_hash::FxHashMap<String, Vec<crate::plugin::external::ReleaseInfo>>,
|
||||
/// The release tag currently selected per linked repo.
|
||||
repo_selected_tag: rustc_hash::FxHashMap<String, String>,
|
||||
/// Repository currently shown in the Plugin Manager detail pane.
|
||||
selected_plugin_repo: Option<String>,
|
||||
/// Parsed GitHub README content or the last fetch error, cached per repo.
|
||||
plugin_readmes:
|
||||
rustc_hash::FxHashMap<String, Result<iced::widget::markdown::Content, String>>,
|
||||
plugin_readmes: rustc_hash::FxHashMap<String, Result<iced::widget::markdown::Content, String>>,
|
||||
/// README requests in flight, used to render a deterministic loading state.
|
||||
plugin_readme_loading: rustc_hash::FxHashSet<String>,
|
||||
/// Last marketplace status / error line shown in the Plugin Manager.
|
||||
@@ -1098,8 +1098,7 @@ pub(super) struct OpenCADStudio {
|
||||
save_job_serial: u64,
|
||||
/// Destination leases held while Save As workers are active.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pending_save_leases:
|
||||
std::collections::HashMap<u64, crate::io::edit_lock::EditLease>,
|
||||
pending_save_leases: std::collections::HashMap<u64, crate::io::edit_lock::EditLease>,
|
||||
/// Locked-file failure currently shown in the recovery dialog.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pending_save_failure: Option<PendingSaveFailure>,
|
||||
@@ -1448,7 +1447,8 @@ impl ClipboardDeps {
|
||||
if !objects.is_empty() {
|
||||
let mut annotation_scales = Vec::new();
|
||||
for (_, object) in &objects {
|
||||
let acadrust::objects::ObjectType::ObjectContextData(context) = object else {
|
||||
let acadrust::objects::ObjectType::ObjectContextData(context) = object
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
if annotation_scales
|
||||
@@ -1618,9 +1618,7 @@ impl ClipboardDeps {
|
||||
fn snapshot_block(doc: &acadrust::CadDocument, name: &str) -> Option<BlockDef> {
|
||||
use acadrust::EntityType;
|
||||
let br = doc.block_records.get(name)?;
|
||||
if name.starts_with("*Model_Space")
|
||||
|| name.starts_with("*Paper_Space")
|
||||
|| br.flags.is_xref
|
||||
if name.starts_with("*Model_Space") || name.starts_with("*Paper_Space") || br.flags.is_xref
|
||||
{
|
||||
return None;
|
||||
}
|
||||
@@ -1835,10 +1833,7 @@ pub enum Message {
|
||||
/// Register a font already held by the shared web store with the UI renderer.
|
||||
ApplyWebFont(crate::scene::text::web_font::Script),
|
||||
/// Completion of the UI renderer's runtime font registration.
|
||||
WebUiFontLoaded(
|
||||
crate::scene::text::web_font::Script,
|
||||
Result<(), String>,
|
||||
),
|
||||
WebUiFontLoaded(crate::scene::text::web_font::Script, Result<(), String>),
|
||||
/// Ctrl+V. Routed by `update` into an open text editor, the drawing-object
|
||||
/// clipboard, or the system text clipboard.
|
||||
PasteShortcut,
|
||||
@@ -1906,10 +1901,13 @@ pub enum Message {
|
||||
WebFileOpened(u64, crate::io::WebOpenOutcome),
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
WebFileCached(u64, crate::io::WebOpenOutcome, Result<(), String>),
|
||||
FileOpened(u64, Result<
|
||||
(String, PathBuf, CadDocument, crate::scene::DerivedCaches),
|
||||
crate::io::OpenLoadError,
|
||||
>),
|
||||
FileOpened(
|
||||
u64,
|
||||
Result<
|
||||
(String, PathBuf, CadDocument, crate::scene::DerivedCaches),
|
||||
crate::io::OpenLoadError,
|
||||
>,
|
||||
),
|
||||
RecoveryClose,
|
||||
RecoveryAttempt,
|
||||
RecoveryDecline,
|
||||
@@ -2121,6 +2119,10 @@ pub enum Message {
|
||||
CommandInput(String),
|
||||
CommandSubmit,
|
||||
Command(String),
|
||||
/// Execute one complete line read from a command script. Unlike UI/ribbon
|
||||
/// dispatch, this accepts an interactive verb and all of its arguments on
|
||||
/// the same line (`BOX 0,0,0 10,10,0 10`).
|
||||
ScriptLine(String),
|
||||
/// Append one typed character to the command-line input from the
|
||||
/// global key-press subscription. Used when the text-input widget
|
||||
/// itself isn't focused (focus parked on viewport / button / etc.)
|
||||
@@ -2150,9 +2152,16 @@ pub enum Message {
|
||||
},
|
||||
/// A widget captured Up/Down; resolve it only if the command input owns
|
||||
/// keyboard focus.
|
||||
CommandLineArrowProbe { direction: ArrowKey, extend_selection: bool },
|
||||
CommandLineArrowProbe {
|
||||
direction: ArrowKey,
|
||||
extend_selection: bool,
|
||||
},
|
||||
/// Result of the command-input focus query for a captured Up/Down key.
|
||||
CommandLineArrowResolved { direction: ArrowKey, focused: bool, extend_selection: bool },
|
||||
CommandLineArrowResolved {
|
||||
direction: ArrowKey,
|
||||
focused: bool,
|
||||
extend_selection: bool,
|
||||
},
|
||||
/// Toggle the dropdown listing the full command-line history.
|
||||
CommandHistoryToggle,
|
||||
/// Grab/move/release the expanded history panel's top resize edge.
|
||||
@@ -2303,9 +2312,7 @@ pub enum Message {
|
||||
epoch: u64,
|
||||
source: usize,
|
||||
wires: std::sync::Weak<Vec<crate::scene::WireModel>>,
|
||||
index: std::sync::Arc<
|
||||
crate::scene::pick::interaction_index::InteractionIndex,
|
||||
>,
|
||||
index: std::sync::Arc<crate::scene::pick::interaction_index::InteractionIndex>,
|
||||
build_ms: f64,
|
||||
},
|
||||
WindowResized(f32, f32),
|
||||
@@ -2567,7 +2574,10 @@ pub enum Message {
|
||||
PropEditChoiceToggle,
|
||||
/// User is typing in a block-attribute value field (live buffer update),
|
||||
/// keyed by the attribute tag.
|
||||
PropAttrInput { tag: String, value: String },
|
||||
PropAttrInput {
|
||||
tag: String,
|
||||
value: String,
|
||||
},
|
||||
/// User committed a block-attribute value edit (Enter pressed).
|
||||
PropAttrCommit(String),
|
||||
/// Reports the currently keyboard-focused widget (if any) after a
|
||||
@@ -2593,7 +2603,10 @@ pub enum Message {
|
||||
PropColorFieldToggle(String),
|
||||
/// User picked a colour for a generic per-field colour row (hatch gradient
|
||||
/// `Color 1` / `Color 2`), routed by the field name.
|
||||
PropColorFieldChanged { field: String, color: AcadColor },
|
||||
PropColorFieldChanged {
|
||||
field: String,
|
||||
color: AcadColor,
|
||||
},
|
||||
/// Collapse the inline color picker dropdown. Fired when another
|
||||
/// properties-panel dropdown (a combo_box) opens, so at most one panel
|
||||
/// dropdown is open at a time and they can't overlap. (#235)
|
||||
@@ -2705,7 +2718,10 @@ pub enum Message {
|
||||
/// Select the row the Text Options / Properties tabs act on.
|
||||
AttrEditorSelect(usize),
|
||||
/// Live edit of the attribute value at row `idx` (Attribute tab).
|
||||
AttrEditorInput { idx: usize, value: String },
|
||||
AttrEditorInput {
|
||||
idx: usize,
|
||||
value: String,
|
||||
},
|
||||
// Text Options — all act on the selected row:
|
||||
AttrEditorTextStyle(String),
|
||||
AttrEditorJustify(String),
|
||||
@@ -2760,9 +2776,7 @@ pub enum Message {
|
||||
/// GitHub Discussions fetched at boot for the Start page.
|
||||
DiscussionsFetched(Result<Vec<crate::discussions::DiscussionEntry>, String>),
|
||||
/// Recent-file DWG preview thumbnails decoded on a background thread.
|
||||
RecentThumbsLoaded(
|
||||
Vec<(std::path::PathBuf, Option<iced::widget::image::Handle>)>,
|
||||
),
|
||||
RecentThumbsLoaded(Vec<(std::path::PathBuf, Option<iced::widget::image::Handle>)>),
|
||||
/// Installable releases and manifest API versions fetched for `owner/repo`.
|
||||
PluginReleasesFetched(
|
||||
String,
|
||||
@@ -2803,7 +2817,10 @@ pub enum Message {
|
||||
InvertSelection,
|
||||
/// Keyboard modifier state changed — tracks whether Shift is held so the
|
||||
/// pick path can do subtractive (Shift+click) selection.
|
||||
SetModifiers { shift: bool, ctrl: bool },
|
||||
SetModifiers {
|
||||
shift: bool,
|
||||
ctrl: bool,
|
||||
},
|
||||
// ── In-place MText editor ───────────────────────────────────────────
|
||||
/// Text-area edit action from the multi-line editor widget.
|
||||
MTextEdit(iced::widget::text_editor::Action),
|
||||
@@ -3273,10 +3290,7 @@ impl OpenCADStudio {
|
||||
.iter()
|
||||
.filter_map(|v| {
|
||||
let bytes = v.thumb.clone()?;
|
||||
Some((
|
||||
v.id.clone(),
|
||||
iced::widget::image::Handle::from_bytes(bytes),
|
||||
))
|
||||
Some((v.id.clone(), iced::widget::image::Handle::from_bytes(bytes)))
|
||||
})
|
||||
.collect();
|
||||
self.videos = videos;
|
||||
@@ -3790,8 +3804,7 @@ impl OpenCADStudio {
|
||||
let state = Self::new();
|
||||
let (id, open_task) = window::open(window::Settings {
|
||||
maximized: true,
|
||||
icon: build_window_icon()
|
||||
.and_then(|rgba| window::icon::from_rgba(rgba, 32, 32).ok()),
|
||||
icon: build_window_icon().and_then(|rgba| window::icon::from_rgba(rgba, 32, 32).ok()),
|
||||
exit_on_close_request: false,
|
||||
// A Wayland compositor has no StartupWMClass to go on: it resolves a
|
||||
// window's dock icon by matching the window's app_id against the
|
||||
@@ -3844,7 +3857,7 @@ impl OpenCADStudio {
|
||||
Task::batch(
|
||||
cfg.script_lines
|
||||
.into_iter()
|
||||
.map(|line| Task::done(Message::Command(line))),
|
||||
.map(|line| Task::done(Message::ScriptLine(line))),
|
||||
)
|
||||
};
|
||||
s.queue_startup_prompts();
|
||||
@@ -3927,24 +3940,17 @@ impl OpenCADStudio {
|
||||
let mut s = Self::new();
|
||||
s.queue_startup_prompts();
|
||||
let focus = s.focus_cmd_input();
|
||||
let primary_font = crate::scene::text::web_font::preload_language(
|
||||
&crate::i18n::active_language_tag(),
|
||||
);
|
||||
let primary_font =
|
||||
crate::scene::text::web_font::preload_language(&crate::i18n::active_language_tag());
|
||||
let fonts = Task::batch([
|
||||
Task::done(Message::PollWebFonts),
|
||||
Task::done(Message::ApplyWebFont(primary_font)),
|
||||
]);
|
||||
// Web can't reach the Patreon API directly (CORS); fetch the CI-built
|
||||
// supporters.json served on the same origin instead.
|
||||
let patrons = Task::perform(
|
||||
crate::patreon::fetch_patrons_web(),
|
||||
Message::PatronsFetched,
|
||||
);
|
||||
let patrons = Task::perform(crate::patreon::fetch_patrons_web(), Message::PatronsFetched);
|
||||
s.videos_loading = true;
|
||||
let videos = Task::perform(
|
||||
crate::videos::fetch_playlist_web(),
|
||||
Message::VideosFetched,
|
||||
);
|
||||
let videos = Task::perform(crate::videos::fetch_playlist_web(), Message::VideosFetched);
|
||||
s.discussions_loading = true;
|
||||
let discussions = Task::perform(
|
||||
crate::discussions::fetch_discussions_web(),
|
||||
@@ -3977,9 +3983,14 @@ pub fn run() -> iced::Result {
|
||||
if let Some(tab) = state.tabs.get(state.active_tab) {
|
||||
let dot = if tab.dirty { "● " } else { "" };
|
||||
let name = tab.tab_display_name();
|
||||
format!("{}OCS-{} - {}", dot, env!("OCS_BUILD_STAMP"), name)
|
||||
format!(
|
||||
"{}Open CAD Studio {} - {}",
|
||||
dot,
|
||||
env!("OCS_APP_VERSION"),
|
||||
name
|
||||
)
|
||||
} else {
|
||||
concat!("OCS-", env!("OCS_BUILD_STAMP")).to_string()
|
||||
concat!("Open CAD Studio ", env!("OCS_APP_VERSION")).to_string()
|
||||
}
|
||||
})
|
||||
.theme(|state: &OpenCADStudio, _| state.active_theme.clone())
|
||||
@@ -4011,7 +4022,9 @@ pub fn run_web() -> iced::Result {
|
||||
OpenCADStudio::view_main,
|
||||
)
|
||||
.subscription(OpenCADStudio::subscription)
|
||||
.title(|_state: &OpenCADStudio| concat!("OCS-", env!("OCS_BUILD_STAMP")).to_string())
|
||||
.title(|_state: &OpenCADStudio| {
|
||||
concat!("Open CAD Studio ", env!("OCS_APP_VERSION")).to_string()
|
||||
})
|
||||
.theme(|state: &OpenCADStudio| state.active_theme.clone())
|
||||
.backend(iced::Backend::Hardware(iced::backend::Api::OpenGL))
|
||||
.font(iced_aw::ICED_AW_FONT_BYTES)
|
||||
|
||||
Reference in new issue
Block a user