Merge main into Pallet-placement

Resolved conflicts:
- app/update/mod.rs: keep the dock's dock_open_at_default for the XREF
  manager; take main's stable xref row identity (row_index(&id)).
- app/view/mod.rs: keep the edge layout from app::dock; drop main's copy
  of the old edge-stack code (main only reformatted it there).
- ui/window/layers.rs: keep main's new visible_indices next to the
  branch's view_panel.
Files the branch only reformatted take main's version. Adds the Lao
(lo-LA) translations for the new dock texts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
This commit is contained in:
Claude committed 2026-10-11 18:44:00 +00:00
commit 2fca3fd18d
136 files changed
+12408 -949

No files matched your search

+11 -6
View File
@@ -202,6 +202,7 @@ impl OpenCADStudio {
crate::perf_record!("[perf] view {:>7.1}ms", elapsed_ms);
}
}
crate::perf::note_view_finish();
element
}
@@ -929,11 +930,14 @@ bg={bg_ms:.1}ms n={view_count}"
snap_angle_deg: self.snap_angle_deg,
pick_pending: self.pending_pick_label().is_some(),
// An infinite-line preview runs along the arms; drop them
// so the preview stays visible (#1437).
hide_arms: tab
.active_cmd
.as_ref()
.is_some_and(|c| matches!(c.name(), "XLINE" | "RAY")),
// so the preview stays visible (#1437). A command asking
// for objects shows the pickbox alone, so picking reads
// apart from both idle and point input (#1661).
hide_arms: tab.active_cmd.as_ref().is_some_and(|c| {
matches!(c.name(), "XLINE" | "RAY")
|| c.needs_entity_pick()
|| c.is_selection_gathering()
}),
snap_color: self.snap_marker_color,
},
crate::ui::overlay::SelectionVisualOptions {
@@ -1898,7 +1902,8 @@ bg={bg_ms:.1}ms n={view_count}"
// collecting its own input. A pending Lengthen / Radius / Arc Length
// value is numeric input, not the prefix of a new command (for example,
// `3` must not open the 3DALIGN / 3DARRAY suggestions).
let allow_autocomplete = tab.active_cmd.is_none() && self.grip_pending.is_none();
let allow_autocomplete = self.grip_pending.is_none()
&& (tab.active_cmd.is_none() || self.command_line.has_contextual_suggestions());
// Dynamic input captures keystrokes when its fields are showing,
// so the command-line field must release focus / its on_input.
// The MText preview also captures keystrokes (typing edits it), so the
+18 -8
View File
@@ -293,6 +293,8 @@ impl OpenCADStudio {
cliprompt_lines: self.cliprompt_lines,
commandline_fade_ms: self.commandline_fade_ms,
zoom_wheel_reversed: self.zoom_wheel_reversed,
touchpad_pan: self.touchpad_pan,
ui_scale_percent: self.ui_scale_percent,
zoom_factor: self.zoom_factor,
texteditmode: self.texteditmode,
dimension_continue_mode: self.dimension_continue_mode,
@@ -619,14 +621,22 @@ impl OpenCADStudio {
}
}
linetypes.sort_by_key(|name| name.to_lowercase());
sized_flow(ex, 1180, 560, |flow| {
crate::ui::window::layer_state_manager::view_editor(
state,
&self.layer_state_edit_filter,
self.layer_state_edit_color_open,
linetypes.clone(),
flow,
)
// Shared ownership: the build closure runs twice per frame
// (INTRINSIC + FILL) and each row keeps its own copy, so a
// borrow cannot work here — an Arc clone per row is a
// refcount bump instead of N string clones (#21, cf. #34).
let linetypes = std::sync::Arc::<[String]>::from(linetypes);
sized_flow(ex, 1180, 560, {
let linetypes = std::sync::Arc::clone(&linetypes);
move |flow| {
crate::ui::window::layer_state_manager::view_editor(
state,
&self.layer_state_edit_filter,
self.layer_state_edit_color_open,
std::sync::Arc::clone(&linetypes),
flow,
)
}
})
} else {
automatic_flow(ex, |flow| {