forked from 1b-agent/opencadstudio-upstream
style: apply cargo fmt across workspace (as on main)
Formats the branch the way main's 9cf9ff2 did, so merging main only
conflicts where the code itself differs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013RyGiMXcsf9HTKfqDxaQGt
This commit is contained in:
532 files changed
+56995
-33416
No files matched your search
+362
-259
@@ -4,13 +4,12 @@
|
||||
use super::util::*;
|
||||
use super::{format_size, VIEWCUBE_HIT_SIZE};
|
||||
use crate::app::helpers::{
|
||||
parse_coord, polar_constrain_near, ucs_rotate_vec, ucs_to_wcs, ucs_z_axis,
|
||||
CoordKind,
|
||||
parse_coord, polar_constrain_near, ucs_rotate_vec, ucs_to_wcs, ucs_z_axis, CoordKind,
|
||||
};
|
||||
use crate::app::{Message, OpenCADStudio, POLY_START_DELAY_MS};
|
||||
use crate::modules::ModuleEvent;
|
||||
use crate::scene::pick::grip::{find_hit_grip, find_hit_grip_paper, find_hit_grip_rte, GripEdit};
|
||||
use crate::scene::model::object::GripApply;
|
||||
use crate::scene::pick::grip::{find_hit_grip, find_hit_grip_paper, find_hit_grip_rte, GripEdit};
|
||||
use crate::scene::{
|
||||
self, hover_id, CubeRegion, Scene, VIEWCUBE_DRAW_PX, VIEWCUBE_PAD, VIEWCUBE_PX,
|
||||
};
|
||||
@@ -20,7 +19,6 @@ use codec::{EntityType as AcadEntityType, Handle};
|
||||
use iced::time::Instant;
|
||||
use iced::{mouse, Point, Task};
|
||||
|
||||
|
||||
impl OpenCADStudio {
|
||||
pub(in crate::app) fn open_save_dialog_window(&mut self, tab_idx: usize) -> Task<Message> {
|
||||
// Default the format dropdown to the loaded file's own format — its
|
||||
@@ -64,7 +62,6 @@ impl OpenCADStudio {
|
||||
Task::none()
|
||||
}
|
||||
|
||||
|
||||
pub(in crate::app) fn close_save_dialog_window(&mut self) -> Task<Message> {
|
||||
self.aec_drop_acknowledged = false;
|
||||
if self.active_modal == Some(crate::app::ModalKind::SaveDialog) {
|
||||
@@ -74,7 +71,6 @@ impl OpenCADStudio {
|
||||
Task::none()
|
||||
}
|
||||
|
||||
|
||||
pub(in crate::app) fn open_unsaved_dialog_window(&mut self) -> Task<Message> {
|
||||
self.active_modal = Some(crate::app::ModalKind::Unsaved);
|
||||
// The unsaved-changes prompt renders inside the main window, so bring
|
||||
@@ -95,7 +91,6 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub(in crate::app) fn close_unsaved_dialog_window(&mut self) -> Task<Message> {
|
||||
if self.active_modal == Some(crate::app::ModalKind::Unsaved) {
|
||||
self.active_modal = None;
|
||||
@@ -104,131 +99,132 @@ impl OpenCADStudio {
|
||||
Task::none()
|
||||
}
|
||||
|
||||
|
||||
pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEvent) -> Task<Message> {
|
||||
// Commands use `start_allowed`; other events need a drawing
|
||||
// and stay blocked on the Start page (#299, #388, #389).
|
||||
if self.tabs[self.active_tab].is_start && !matches!(event, ModuleEvent::Command(_)) {
|
||||
self.ribbon.close_dropdown();
|
||||
self.command_line
|
||||
.push_info(crate::t!("No drawing open — use New or Open first.").as_ref());
|
||||
return Task::none();
|
||||
}
|
||||
// Dismiss any open dropdown / collapsed-panel flyout on tool use,
|
||||
// and remember this tool as its panel's last-used one.
|
||||
self.ribbon.close_dropdown();
|
||||
self.ribbon.note_panel_tool(&tool_id);
|
||||
self.ribbon.activate_tool(&tool_id);
|
||||
match event {
|
||||
// `dispatch_command` turns a one-shot tool's highlight off
|
||||
// again once nothing is left running (#355).
|
||||
ModuleEvent::Command(cmd) => return self.dispatch_command(&cmd),
|
||||
ModuleEvent::OpenFileDialog => {
|
||||
pub(super) fn on_ribbon_tool_click(
|
||||
&mut self,
|
||||
tool_id: String,
|
||||
event: ModuleEvent,
|
||||
) -> Task<Message> {
|
||||
// Commands use `start_allowed`; other events need a drawing
|
||||
// and stay blocked on the Start page (#299, #388, #389).
|
||||
if self.tabs[self.active_tab].is_start && !matches!(event, ModuleEvent::Command(_)) {
|
||||
self.ribbon.close_dropdown();
|
||||
self.command_line
|
||||
.push_info(crate::t!("No drawing open — use New or Open first.").as_ref());
|
||||
return Task::none();
|
||||
}
|
||||
// Dismiss any open dropdown / collapsed-panel flyout on tool use,
|
||||
// and remember this tool as its panel's last-used one.
|
||||
self.ribbon.close_dropdown();
|
||||
self.ribbon.note_panel_tool(&tool_id);
|
||||
self.ribbon.activate_tool(&tool_id);
|
||||
match event {
|
||||
// `dispatch_command` turns a one-shot tool's highlight off
|
||||
// again once nothing is left running (#355).
|
||||
ModuleEvent::Command(cmd) => return self.dispatch_command(&cmd),
|
||||
ModuleEvent::OpenFileDialog => {
|
||||
self.command_line
|
||||
.push_info(crate::t!("Open DWG/DXF: not yet implemented.").as_ref());
|
||||
}
|
||||
ModuleEvent::ClearModels => {
|
||||
let i = self.active_tab;
|
||||
self.tabs[i].scene.clear();
|
||||
self.tabs[i].properties = PropertiesPanel::empty();
|
||||
self.command_line
|
||||
.push_output(crate::t!("Scene cleared.").as_ref());
|
||||
}
|
||||
ModuleEvent::SetVisualStyle(name) => {
|
||||
use crate::modules::view::visual_style;
|
||||
match visual_style::mode_for_keyword(&name) {
|
||||
Some(mode) => return Task::done(Message::SetRenderMode(mode)),
|
||||
None => {
|
||||
// Name the styles that do exist, from the same
|
||||
// list every other caller reads.
|
||||
self.command_line
|
||||
.push_info(crate::t!("Open DWG/DXF: not yet implemented.").as_ref());
|
||||
}
|
||||
ModuleEvent::ClearModels => {
|
||||
let i = self.active_tab;
|
||||
self.tabs[i].scene.clear();
|
||||
self.tabs[i].properties = PropertiesPanel::empty();
|
||||
self.command_line.push_output(crate::t!("Scene cleared.").as_ref());
|
||||
}
|
||||
ModuleEvent::SetVisualStyle(name) => {
|
||||
use crate::modules::view::visual_style;
|
||||
match visual_style::mode_for_keyword(&name) {
|
||||
Some(mode) => return Task::done(Message::SetRenderMode(mode)),
|
||||
None => {
|
||||
// Name the styles that do exist, from the same
|
||||
// list every other caller reads.
|
||||
self.command_line.push_error(
|
||||
crate::tf!("Unknown visual style \"{name}\".").as_ref(),
|
||||
);
|
||||
self.command_line
|
||||
.push_info(crate::t!(visual_style::keyword_prompt()).as_ref());
|
||||
}
|
||||
}
|
||||
}
|
||||
ModuleEvent::ToggleLayers => {
|
||||
return Task::done(Message::ToggleLayers);
|
||||
}
|
||||
ModuleEvent::PluginFileDialog {
|
||||
command,
|
||||
title,
|
||||
filter_name,
|
||||
extensions,
|
||||
} => {
|
||||
return Task::perform(
|
||||
async move {
|
||||
let exts: Vec<&str> =
|
||||
extensions.iter().map(|s| s.as_str()).collect();
|
||||
let path = crate::sys::file_dialog()
|
||||
.set_title(title)
|
||||
.add_filter(filter_name, &exts)
|
||||
.add_filter(crate::t!("All Files").as_ref(), &["*"])
|
||||
.pick_file()
|
||||
.await
|
||||
.map(|h| crate::sys::handle_path(&h));
|
||||
(command, path)
|
||||
},
|
||||
|(command, path)| Message::PluginFileDialogResult { command, path },
|
||||
);
|
||||
.push_error(crate::tf!("Unknown visual style \"{name}\".").as_ref());
|
||||
self.command_line
|
||||
.push_info(crate::t!(visual_style::keyword_prompt()).as_ref());
|
||||
}
|
||||
}
|
||||
// Every non-Command event above is a one-shot (state toggle,
|
||||
// clear, dialog spawn) — nothing stays running to clear the
|
||||
// highlight later, so turn it off here. (#355)
|
||||
self.ribbon.deactivate_tool();
|
||||
Task::none()
|
||||
}
|
||||
ModuleEvent::ToggleLayers => {
|
||||
return Task::done(Message::ToggleLayers);
|
||||
}
|
||||
ModuleEvent::PluginFileDialog {
|
||||
command,
|
||||
title,
|
||||
filter_name,
|
||||
extensions,
|
||||
} => {
|
||||
return Task::perform(
|
||||
async move {
|
||||
let exts: Vec<&str> = extensions.iter().map(|s| s.as_str()).collect();
|
||||
let path = crate::sys::file_dialog()
|
||||
.set_title(title)
|
||||
.add_filter(filter_name, &exts)
|
||||
.add_filter(crate::t!("All Files").as_ref(), &["*"])
|
||||
.pick_file()
|
||||
.await
|
||||
.map(|h| crate::sys::handle_path(&h));
|
||||
(command, path)
|
||||
},
|
||||
|(command, path)| Message::PluginFileDialogResult { command, path },
|
||||
);
|
||||
}
|
||||
}
|
||||
// Every non-Command event above is a one-shot (state toggle,
|
||||
// clear, dialog spawn) — nothing stays running to clear the
|
||||
// highlight later, so turn it off here. (#355)
|
||||
self.ribbon.deactivate_tool();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
pub(super) fn on_unsaved_dialog_discard(&mut self) -> Task<Message> {
|
||||
match self.pending_close.take() {
|
||||
Some(crate::app::PendingClose::Tab(tab_id)) => {
|
||||
let close_win = self.close_unsaved_dialog_window();
|
||||
// Resolve the id now: the tab may have closed while
|
||||
// the dialog was open (batched close, automation),
|
||||
// in which case there is nothing left to discard.
|
||||
let Some(idx) = self.tabs.iter().position(|t| t.id == tab_id) else {
|
||||
return Task::batch([close_win, self.continue_tab_close_queue()]);
|
||||
};
|
||||
// Discarded — drop this tab's autosave recovery copy.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let _ = std::fs::remove_file(self.autosave_target(idx));
|
||||
if self.tabs.len() == 1 {
|
||||
self.tab_counter += 1;
|
||||
self.tabs[0] =
|
||||
crate::app::document::DocumentTab::new_drawing(self.tab_counter);
|
||||
self.active_tab = 0;
|
||||
self.apply_display_defaults(0);
|
||||
} else {
|
||||
self.tabs.remove(idx);
|
||||
if self.active_tab >= self.tabs.len() {
|
||||
self.active_tab = self.tabs.len() - 1;
|
||||
}
|
||||
}
|
||||
// The active tab is now a fresh blank or a
|
||||
// different existing tab; sync ribbon chips so
|
||||
// they don't keep showing the discarded tab's
|
||||
// last selection. #21.
|
||||
self.sync_ribbon_layers();
|
||||
self.sync_ribbon_from_selection();
|
||||
return Task::batch([close_win, self.continue_tab_close_queue()]);
|
||||
match self.pending_close.take() {
|
||||
Some(crate::app::PendingClose::Tab(tab_id)) => {
|
||||
let close_win = self.close_unsaved_dialog_window();
|
||||
// Resolve the id now: the tab may have closed while
|
||||
// the dialog was open (batched close, automation),
|
||||
// in which case there is nothing left to discard.
|
||||
let Some(idx) = self.tabs.iter().position(|t| t.id == tab_id) else {
|
||||
return Task::batch([close_win, self.continue_tab_close_queue()]);
|
||||
};
|
||||
// Discarded — drop this tab's autosave recovery copy.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let _ = std::fs::remove_file(self.autosave_target(idx));
|
||||
if self.tabs.len() == 1 {
|
||||
self.tab_counter += 1;
|
||||
self.tabs[0] = crate::app::document::DocumentTab::new_drawing(self.tab_counter);
|
||||
self.active_tab = 0;
|
||||
self.apply_display_defaults(0);
|
||||
} else {
|
||||
self.tabs.remove(idx);
|
||||
if self.active_tab >= self.tabs.len() {
|
||||
self.active_tab = self.tabs.len() - 1;
|
||||
}
|
||||
Some(crate::app::PendingClose::Quit) => {
|
||||
if let Some(idx) = self.tabs.iter().position(|t| t.dirty) {
|
||||
self.tabs[idx].dirty = false;
|
||||
}
|
||||
if self.tabs.iter().any(|t| t.dirty) {
|
||||
// More dirty tabs remain — keep window open.
|
||||
self.pending_close = Some(crate::app::PendingClose::Quit);
|
||||
} else {
|
||||
let close_win = self.close_unsaved_dialog_window();
|
||||
return Task::batch(vec![close_win, self.exit_app()]);
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
Task::none()
|
||||
// The active tab is now a fresh blank or a
|
||||
// different existing tab; sync ribbon chips so
|
||||
// they don't keep showing the discarded tab's
|
||||
// last selection. #21.
|
||||
self.sync_ribbon_layers();
|
||||
self.sync_ribbon_from_selection();
|
||||
return Task::batch([close_win, self.continue_tab_close_queue()]);
|
||||
}
|
||||
Some(crate::app::PendingClose::Quit) => {
|
||||
if let Some(idx) = self.tabs.iter().position(|t| t.dirty) {
|
||||
self.tabs[idx].dirty = false;
|
||||
}
|
||||
if self.tabs.iter().any(|t| t.dirty) {
|
||||
// More dirty tabs remain — keep window open.
|
||||
self.pending_close = Some(crate::app::PendingClose::Quit);
|
||||
} else {
|
||||
let close_win = self.close_unsaved_dialog_window();
|
||||
return Task::batch(vec![close_win, self.exit_app()]);
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
pub(super) fn on_unsaved_dialog_save(&mut self) -> Task<Message> {
|
||||
@@ -254,10 +250,7 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
crate::app::PendingClose::Quit => {
|
||||
let Some(idx) = self.tabs.iter().position(|tab| tab.dirty) else {
|
||||
self.pending_close = None;
|
||||
return Task::batch([
|
||||
self.close_unsaved_dialog_window(),
|
||||
self.exit_app(),
|
||||
]);
|
||||
return Task::batch([self.close_unsaved_dialog_window(), self.exit_app()]);
|
||||
};
|
||||
(idx, crate::app::SaveContinuation::Quit)
|
||||
}
|
||||
@@ -319,10 +312,7 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
let save = self.save_with_default_format(idx);
|
||||
Task::batch([close, save])
|
||||
} else {
|
||||
Task::batch([
|
||||
self.close_unsaved_dialog_window(),
|
||||
self.exit_app(),
|
||||
])
|
||||
Task::batch([self.close_unsaved_dialog_window(), self.exit_app()])
|
||||
}
|
||||
}
|
||||
None => Task::none(),
|
||||
@@ -356,7 +346,10 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
/// one new block in the active drawing. Returns the new block's name, or an
|
||||
/// error message. Nested block definitions are imported first so nested
|
||||
/// INSERTs render (AutoCAD's "inserting a drawing imports its block defs").
|
||||
pub(in crate::app) fn import_file_as_block(&mut self, path: std::path::PathBuf) -> Result<String, String> {
|
||||
pub(in crate::app) fn import_file_as_block(
|
||||
&mut self,
|
||||
path: std::path::PathBuf,
|
||||
) -> Result<String, String> {
|
||||
self.import_drawing_block(path, false)
|
||||
}
|
||||
|
||||
@@ -417,7 +410,10 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
.iter()
|
||||
.filter_map(|h| doc.get_entity(*h))
|
||||
.filter(|e| {
|
||||
!matches!(e, codec::EntityType::Block(_) | codec::EntityType::BlockEnd(_))
|
||||
!matches!(
|
||||
e,
|
||||
codec::EntityType::Block(_) | codec::EntityType::BlockEnd(_)
|
||||
)
|
||||
})
|
||||
.cloned()
|
||||
.collect()
|
||||
@@ -430,7 +426,10 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
o == model_br || o.is_null()
|
||||
})
|
||||
.filter(|e| {
|
||||
!matches!(e, codec::EntityType::Block(_) | codec::EntityType::BlockEnd(_))
|
||||
!matches!(
|
||||
e,
|
||||
codec::EntityType::Block(_) | codec::EntityType::BlockEnd(_)
|
||||
)
|
||||
})
|
||||
.cloned()
|
||||
.collect()
|
||||
@@ -445,7 +444,12 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
doc.header.model_space_insertion_base.z,
|
||||
);
|
||||
let redefine = redefine
|
||||
&& self.tabs[i].scene.document.block_records.get(stem.trim()).is_some();
|
||||
&& self.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.block_records
|
||||
.get(stem.trim())
|
||||
.is_some();
|
||||
let name = if redefine {
|
||||
stem.trim().to_string()
|
||||
} else {
|
||||
@@ -622,12 +626,16 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
.entities()
|
||||
.filter_map(|entity| match entity {
|
||||
codec::EntityType::RasterImage(image)
|
||||
if image.definition_handle.is_some_and(|key| self.tabs[i].xref_unloaded.is_unloaded(key.value())) =>
|
||||
if image
|
||||
.definition_handle
|
||||
.is_some_and(|key| self.tabs[i].xref_unloaded.is_unloaded(key.value())) =>
|
||||
{
|
||||
Some(entity.common().handle)
|
||||
}
|
||||
codec::EntityType::Underlay(underlay)
|
||||
if self.tabs[i].xref_unloaded.is_unloaded(underlay.definition_handle.value()) =>
|
||||
if self.tabs[i]
|
||||
.xref_unloaded
|
||||
.is_unloaded(underlay.definition_handle.value()) =>
|
||||
{
|
||||
Some(entity.common().handle)
|
||||
}
|
||||
@@ -646,12 +654,14 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
/// selection. Same engine fns as the CLI arms, batched with per-item
|
||||
/// report lines in the CLI wording; finishes with [`post_ref_op`] plus
|
||||
/// a palette rescan (mirror of the CLI post-op sequence).
|
||||
pub(crate) fn xref_manager_op(
|
||||
&mut self,
|
||||
op: crate::ui::window::xref_manager::XrefPaletteOp,
|
||||
) {
|
||||
pub(crate) fn xref_manager_op(&mut self, op: crate::ui::window::xref_manager::XrefPaletteOp) {
|
||||
if cfg!(target_arch = "wasm32") {
|
||||
self.command_line.push_error(crate::t!("Reference changes are not available on web — the reference list is read-only.").as_ref());
|
||||
self.command_line.push_error(
|
||||
crate::t!(
|
||||
"Reference changes are not available on web — the reference list is read-only."
|
||||
)
|
||||
.as_ref(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
use crate::ui::window::xref_manager::XrefPaletteOp;
|
||||
@@ -664,14 +674,10 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
idx.sort_unstable();
|
||||
idx.iter()
|
||||
.filter_map(|idx| {
|
||||
self.xref_manager.entries.get(*idx).map(|e| {
|
||||
(
|
||||
e.key,
|
||||
e.name.clone(),
|
||||
e.kind,
|
||||
e.parent_key.is_some(),
|
||||
)
|
||||
})
|
||||
self.xref_manager
|
||||
.entries
|
||||
.get(*idx)
|
||||
.map(|e| (e.key, e.name.clone(), e.kind, e.parent_key.is_some()))
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
@@ -686,8 +692,9 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
);
|
||||
let host: Option<std::path::PathBuf> = self.tabs[i].current_path.clone();
|
||||
if needs_host && host.is_none() {
|
||||
self.command_line
|
||||
.push_error(crate::t!("XREF Save the drawing first to resolve relative XREF paths.").as_ref());
|
||||
self.command_line.push_error(
|
||||
crate::t!("XREF Save the drawing first to resolve relative XREF paths.").as_ref(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
let label = match op {
|
||||
@@ -712,15 +719,11 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
).as_ref());
|
||||
continue;
|
||||
}
|
||||
match crate::io::xref::detach_reference(
|
||||
&mut self.tabs[i].scene.document,
|
||||
*key,
|
||||
) {
|
||||
match crate::io::xref::detach_reference(&mut self.tabs[i].scene.document, *key)
|
||||
{
|
||||
Ok(name) => {
|
||||
self.command_line.push_output(crate::tf!(
|
||||
"XREF: detached \"{}\".",
|
||||
name
|
||||
).as_ref());
|
||||
self.command_line
|
||||
.push_output(crate::tf!("XREF: detached \"{}\".", name).as_ref());
|
||||
self.tabs[i].xref_unloaded.remove(key);
|
||||
self.tabs[i].xref_stat_cache.remove(key);
|
||||
done += 1;
|
||||
@@ -738,15 +741,11 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
).as_ref());
|
||||
continue;
|
||||
}
|
||||
match crate::io::xref::unload_reference(
|
||||
&mut self.tabs[i].scene.document,
|
||||
*key,
|
||||
) {
|
||||
match crate::io::xref::unload_reference(&mut self.tabs[i].scene.document, *key)
|
||||
{
|
||||
Ok(name) => {
|
||||
self.command_line.push_output(crate::tf!(
|
||||
"XREF: unloaded \"{}\".",
|
||||
name
|
||||
).as_ref());
|
||||
self.command_line
|
||||
.push_output(crate::tf!("XREF: unloaded \"{}\".", name).as_ref());
|
||||
self.tabs[i].xref_unloaded.add(*key);
|
||||
done += 1;
|
||||
}
|
||||
@@ -810,10 +809,10 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
}
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
} else if *kind != crate::io::xref_model::RefKind::DwgXref {
|
||||
self.command_line.push_error(crate::tf!(
|
||||
"{}: reload applies to drawing references only.",
|
||||
name
|
||||
).as_ref());
|
||||
self.command_line.push_error(
|
||||
crate::tf!("{}: reload applies to drawing references only.", name)
|
||||
.as_ref(),
|
||||
);
|
||||
}
|
||||
}
|
||||
for (key, _) in &dwg_picked {
|
||||
@@ -853,18 +852,14 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
}
|
||||
}
|
||||
for (_, name) in &dwg_picked {
|
||||
match infos
|
||||
.iter()
|
||||
.find(|n| n.name.eq_ignore_ascii_case(name))
|
||||
{
|
||||
match infos.iter().find(|n| n.name.eq_ignore_ascii_case(name)) {
|
||||
Some(info) => {
|
||||
self.report_xref_status(info);
|
||||
done += 1;
|
||||
}
|
||||
None => self.command_line.push_error(crate::tf!(
|
||||
"XREF: no references match '{}'.",
|
||||
name
|
||||
).as_ref()),
|
||||
None => self.command_line.push_error(
|
||||
crate::tf!("XREF: no references match '{}'.", name).as_ref(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -883,10 +878,9 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
crate::io::xref_model::RefType::Overlay,
|
||||
) {
|
||||
Ok(name) => {
|
||||
self.command_line.push_output(crate::tf!(
|
||||
"XREF: \"{}\" set to Overlay.",
|
||||
name
|
||||
).as_ref());
|
||||
self.command_line.push_output(
|
||||
crate::tf!("XREF: \"{}\" set to Overlay.", name).as_ref(),
|
||||
);
|
||||
done += 1;
|
||||
}
|
||||
Err(msg) => self.command_line.push_error(msg.as_str()),
|
||||
@@ -908,10 +902,9 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
crate::io::xref_model::RefType::Attach,
|
||||
) {
|
||||
Ok(name) => {
|
||||
self.command_line.push_output(crate::tf!(
|
||||
"XREF: \"{}\" set to Attach.",
|
||||
name
|
||||
).as_ref());
|
||||
self.command_line.push_output(
|
||||
crate::tf!("XREF: \"{}\" set to Attach.", name).as_ref(),
|
||||
);
|
||||
done += 1;
|
||||
}
|
||||
Err(msg) => self.command_line.push_error(msg.as_str()),
|
||||
@@ -929,10 +922,13 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
.unwrap_or_else(|| std::path::PathBuf::from("."));
|
||||
for (key, name, _, is_nested) in &picked {
|
||||
if *is_nested {
|
||||
self.command_line.push_error(crate::tf!(
|
||||
self.command_line.push_error(
|
||||
crate::tf!(
|
||||
"XREF: cannot bind nested reference '{}'. Bind it in its host drawing.",
|
||||
name
|
||||
).as_ref());
|
||||
)
|
||||
.as_ref(),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
match crate::io::xref::bind_reference(
|
||||
@@ -943,10 +939,9 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
) {
|
||||
Ok(outcome) => {
|
||||
if outcome.unremapped == 0 {
|
||||
self.command_line.push_output(crate::tf!(
|
||||
"XREF: bound \"{}\".",
|
||||
outcome.name
|
||||
).as_ref());
|
||||
self.command_line.push_output(
|
||||
crate::tf!("XREF: bound \"{}\".", outcome.name).as_ref(),
|
||||
);
|
||||
} else {
|
||||
self.command_line.push_output(crate::tf!(
|
||||
"XREF: bound \"{}\" with {} unremapped style handles (see bind limitations).",
|
||||
@@ -978,10 +973,10 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
&host,
|
||||
) {
|
||||
Ok(_) => {
|
||||
self.command_line.push_output(crate::tf!(
|
||||
"XREF: Path set for \"{}\" — Reload to apply.",
|
||||
name
|
||||
).as_ref());
|
||||
self.command_line.push_output(
|
||||
crate::tf!("XREF: Path set for \"{}\" — Reload to apply.", name)
|
||||
.as_ref(),
|
||||
);
|
||||
done += 1;
|
||||
}
|
||||
Err(msg) => self.command_line.push_error(msg.as_str()),
|
||||
@@ -1003,18 +998,25 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
|
||||
/// full resolve, per-ref report, stat baselines refreshed.
|
||||
pub(crate) fn xref_manager_reload_all(&mut self) {
|
||||
if cfg!(target_arch = "wasm32") {
|
||||
self.command_line.push_error(crate::t!("Reference changes are not available on web — the reference list is read-only.").as_ref());
|
||||
self.command_line.push_error(
|
||||
crate::t!(
|
||||
"Reference changes are not available on web — the reference list is read-only."
|
||||
)
|
||||
.as_ref(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
let i = self.active_tab;
|
||||
let Some(path) = self.tabs[i].current_path.clone() else {
|
||||
self.command_line
|
||||
.push_error(crate::t!("XREF Save the drawing first to resolve relative XREF paths.").as_ref());
|
||||
self.command_line.push_error(
|
||||
crate::t!("XREF Save the drawing first to resolve relative XREF paths.").as_ref(),
|
||||
);
|
||||
return;
|
||||
};
|
||||
let Some(base_dir) = path.parent().map(|p| p.to_path_buf()) else {
|
||||
self.command_line
|
||||
.push_error(crate::t!("XREF Save the drawing first to resolve relative XREF paths.").as_ref());
|
||||
self.command_line.push_error(
|
||||
crate::t!("XREF Save the drawing first to resolve relative XREF paths.").as_ref(),
|
||||
);
|
||||
return;
|
||||
};
|
||||
let reload_keys: Vec<u64> = crate::io::xref::collect_entries_with_prev(
|
||||
@@ -1096,7 +1098,9 @@ mod tests {
|
||||
fn import_document_as_block_defines_block() {
|
||||
let mut app = fresh();
|
||||
let doc = foreign_doc(&app);
|
||||
let name = app.import_document_as_block(doc, "Fixture".to_string()).unwrap();
|
||||
let name = app
|
||||
.import_document_as_block(doc, "Fixture".to_string())
|
||||
.unwrap();
|
||||
assert_eq!(name, "Fixture");
|
||||
assert!(app.tabs[app.active_tab]
|
||||
.scene
|
||||
@@ -1119,9 +1123,7 @@ mod tests {
|
||||
.objects
|
||||
.values()
|
||||
.find_map(|o| match o {
|
||||
codec::objects::ObjectType::Layout(l) if l.name == "Model" => {
|
||||
Some(l.block_record)
|
||||
}
|
||||
codec::objects::ObjectType::Layout(l) if l.name == "Model" => Some(l.block_record),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -1191,15 +1193,14 @@ mod tests {
|
||||
}
|
||||
|
||||
/// The nested-INSERT's block name inside a defined block record.
|
||||
fn nested_insert_target(
|
||||
doc: &codec::CadDocument,
|
||||
block: &str,
|
||||
) -> Option<String> {
|
||||
fn nested_insert_target(doc: &codec::CadDocument, block: &str) -> Option<String> {
|
||||
let br = doc.block_records.get(block)?;
|
||||
br.entity_handles.iter().find_map(|h| match doc.get_entity(*h)? {
|
||||
EntityType::Insert(ins) => Some(ins.block_name.clone()),
|
||||
_ => None,
|
||||
})
|
||||
br.entity_handles
|
||||
.iter()
|
||||
.find_map(|h| match doc.get_entity(*h)? {
|
||||
EntityType::Insert(ins) => Some(ins.block_name.clone()),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
/// A foreign document whose model space INSERTs a `Fixture` block whose
|
||||
@@ -1276,7 +1277,9 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let _ = app.import_document_as_block(doc, "Imported".to_string()).unwrap();
|
||||
let _ = app
|
||||
.import_document_as_block(doc, "Imported".to_string())
|
||||
.unwrap();
|
||||
let doc = &app.tabs[i].scene.document;
|
||||
// The file's own "Door (2)" is kept intact and targets the file's
|
||||
// renamed "Door" (now "Door (3)" — "Door (2)" was taken by the source).
|
||||
@@ -1323,7 +1326,9 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let name = app.import_document_as_block(doc, "Imported".to_string()).unwrap();
|
||||
let name = app
|
||||
.import_document_as_block(doc, "Imported".to_string())
|
||||
.unwrap();
|
||||
assert_eq!(name, "Imported");
|
||||
|
||||
let doc = &app.tabs[i].scene.document;
|
||||
@@ -1354,11 +1359,16 @@ mod tests {
|
||||
fn blockpalette_refresh_lists_and_places_block() {
|
||||
let mut app = fresh();
|
||||
let doc = foreign_doc(&app);
|
||||
let name = app.import_document_as_block(doc, "Fixture".to_string()).unwrap();
|
||||
let name = app
|
||||
.import_document_as_block(doc, "Fixture".to_string())
|
||||
.unwrap();
|
||||
app.refresh_block_palette();
|
||||
assert!(app.block_palette.blocks.iter().any(|b| b.name == "Fixture"));
|
||||
app.start_block_placement(&name);
|
||||
let cmd = app.tabs[app.active_tab].active_cmd.as_ref().expect("INSERT running");
|
||||
let cmd = app.tabs[app.active_tab]
|
||||
.active_cmd
|
||||
.as_ref()
|
||||
.expect("INSERT running");
|
||||
assert_eq!(cmd.name(), "-INSERT");
|
||||
assert_eq!(app.block_palette.placing.as_deref(), Some("Fixture"));
|
||||
}
|
||||
@@ -1415,7 +1425,11 @@ mod tests {
|
||||
line.end = Vector3::new(1.0, 0.0, 0.0);
|
||||
app.tabs[i]
|
||||
.scene
|
||||
.define_block_from_owned_entities(vec![EntityType::Line(line)], "Chair", glam::DVec3::ZERO)
|
||||
.define_block_from_owned_entities(
|
||||
vec![EntityType::Line(line)],
|
||||
"Chair",
|
||||
glam::DVec3::ZERO,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(app.block_name_from_file("Chair"), "Chair (2)");
|
||||
assert_eq!(app.block_name_from_file("Table"), "Table");
|
||||
@@ -1444,12 +1458,7 @@ mod tests {
|
||||
br.flags.is_xref = true;
|
||||
br.xref_path = "refs/plan.dwg".to_string();
|
||||
br.handle = app.tabs[i].scene.document.allocate_handle();
|
||||
app.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.block_records
|
||||
.add(br)
|
||||
.unwrap();
|
||||
app.tabs[i].scene.document.block_records.add(br).unwrap();
|
||||
app.tabs[i].current_path = Some(old_dir.join("host.dwg"));
|
||||
let tab_id = app.tabs[i].id;
|
||||
let job_id = 4242u64;
|
||||
@@ -1510,9 +1519,9 @@ mod tests {
|
||||
// Behavioral matrix: every row op on a NESTED row via the GUI
|
||||
// message path. Nested rows must report per-entry errors (CLI
|
||||
// wording), never silently skip.
|
||||
use codec::tables::BlockRecord;
|
||||
use crate::app::Message;
|
||||
use crate::ui::window::xref_manager::XrefPaletteOp;
|
||||
use codec::tables::BlockRecord;
|
||||
let dir = palette_tmpdir("nestedmatrix");
|
||||
let mut host_doc = codec::CadDocument::new();
|
||||
let mut inner = BlockRecord::new("INNER");
|
||||
@@ -1530,7 +1539,12 @@ mod tests {
|
||||
app.tabs[i].scene.document.block_records.add(br).unwrap();
|
||||
app.tabs[i].current_path = Some(dir.join("app.dwg"));
|
||||
app.refresh_xref_manager();
|
||||
let idx = app.xref_manager.entries.iter().position(|e| e.name == "INNER").expect("nested INNER listed");
|
||||
let idx = app
|
||||
.xref_manager
|
||||
.entries
|
||||
.iter()
|
||||
.position(|e| e.name == "INNER")
|
||||
.expect("nested INNER listed");
|
||||
assert!(app.xref_manager.entries[idx].parent_key.is_some());
|
||||
for op in [
|
||||
XrefPaletteOp::Detach,
|
||||
@@ -1542,9 +1556,17 @@ mod tests {
|
||||
let start = app.command_line.history.len();
|
||||
let _ = app.update(Message::XrefRowOp(idx, op));
|
||||
let out = palette_output(&app, start);
|
||||
assert!(out.contains("INNER"), "op {op:?} on nested row gave: {out:?}");
|
||||
assert!(
|
||||
app.tabs[i].scene.document.block_records.get("HOST").is_some(),
|
||||
out.contains("INNER"),
|
||||
"op {op:?} on nested row gave: {out:?}"
|
||||
);
|
||||
assert!(
|
||||
app.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.block_records
|
||||
.get("HOST")
|
||||
.is_some(),
|
||||
"op {op:?} must not mutate the direct reference"
|
||||
);
|
||||
}
|
||||
@@ -1555,9 +1577,9 @@ mod tests {
|
||||
fn palette_detach_unload_rowop_gui_path() {
|
||||
// Reproduction for "Detach/Unload from the palette do nothing":
|
||||
// drive the exact GUI message path (row right-click menu item).
|
||||
use codec::tables::BlockRecord;
|
||||
use crate::app::Message;
|
||||
use crate::ui::window::xref_manager::XrefPaletteOp;
|
||||
use codec::tables::BlockRecord;
|
||||
let mut app = fresh();
|
||||
let i = app.active_tab;
|
||||
for name in ["PLAN", "SITE"] {
|
||||
@@ -1569,19 +1591,42 @@ mod tests {
|
||||
}
|
||||
app.tabs[i].current_path = Some(std::env::temp_dir().join("ocs_repro_host.dwg"));
|
||||
app.refresh_xref_manager();
|
||||
let idx = app.xref_manager.entries.iter().position(|e| e.name == "PLAN").expect("PLAN listed");
|
||||
let idx = app
|
||||
.xref_manager
|
||||
.entries
|
||||
.iter()
|
||||
.position(|e| e.name == "PLAN")
|
||||
.expect("PLAN listed");
|
||||
let start = app.command_line.history.len();
|
||||
let _ = app.update(Message::XrefRowOp(idx, XrefPaletteOp::Detach));
|
||||
let out = palette_output(&app, start);
|
||||
assert!(out.contains("PLAN"), "detach output missing, got: {out:?}");
|
||||
assert!(app.tabs[i].scene.document.block_records.get("PLAN").is_none(), "PLAN definition must be gone");
|
||||
let idx = app.xref_manager.entries.iter().position(|e| e.name == "SITE").expect("SITE listed");
|
||||
assert!(
|
||||
app.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.block_records
|
||||
.get("PLAN")
|
||||
.is_none(),
|
||||
"PLAN definition must be gone"
|
||||
);
|
||||
let idx = app
|
||||
.xref_manager
|
||||
.entries
|
||||
.iter()
|
||||
.position(|e| e.name == "SITE")
|
||||
.expect("SITE listed");
|
||||
let start = app.command_line.history.len();
|
||||
let _ = app.update(Message::XrefRowOp(idx, XrefPaletteOp::Unload));
|
||||
let out = palette_output(&app, start);
|
||||
assert!(out.contains("SITE"), "unload output missing, got: {out:?}");
|
||||
assert_eq!(
|
||||
app.xref_manager.entries.iter().find(|e| e.name == "SITE").unwrap().status,
|
||||
app.xref_manager
|
||||
.entries
|
||||
.iter()
|
||||
.find(|e| e.name == "SITE")
|
||||
.unwrap()
|
||||
.status,
|
||||
crate::io::xref_model::RefStatus::Unloaded
|
||||
);
|
||||
}
|
||||
@@ -1590,10 +1635,10 @@ mod tests {
|
||||
fn palette_overlay_and_pathtype_rowop_gui_path() {
|
||||
// Row-menu Overlay + Change-Path row ops on a direct row via the
|
||||
// GUI message path: type flag flips, saved path clears.
|
||||
use codec::tables::BlockRecord;
|
||||
use crate::app::Message;
|
||||
use crate::io::xref_model::{Pathtype, RefType};
|
||||
use crate::ui::window::xref_manager::XrefPaletteOp;
|
||||
use codec::tables::BlockRecord;
|
||||
let mut app = fresh();
|
||||
let i = app.active_tab;
|
||||
let mut br = BlockRecord::new("PLAN");
|
||||
@@ -1603,20 +1648,49 @@ mod tests {
|
||||
app.tabs[i].scene.document.block_records.add(br).unwrap();
|
||||
app.tabs[i].current_path = Some(std::env::temp_dir().join("ocs_rowop_host.dwg"));
|
||||
app.refresh_xref_manager();
|
||||
let idx = app.xref_manager.entries.iter().position(|e| e.name == "PLAN").expect("PLAN listed");
|
||||
let idx = app
|
||||
.xref_manager
|
||||
.entries
|
||||
.iter()
|
||||
.position(|e| e.name == "PLAN")
|
||||
.expect("PLAN listed");
|
||||
let start = app.command_line.history.len();
|
||||
let _ = app.update(Message::XrefRowOp(idx, XrefPaletteOp::Overlay));
|
||||
let out = palette_output(&app, start);
|
||||
assert!(out.contains("PLAN"), "got: {out:?}");
|
||||
let br = app.tabs[i].scene.document.block_records.get("PLAN").unwrap();
|
||||
let br = app.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.block_records
|
||||
.get("PLAN")
|
||||
.unwrap();
|
||||
assert!(br.flags.is_xref_overlay && !br.flags.is_xref);
|
||||
assert_eq!(app.xref_manager.entries.iter().find(|e| e.name == "PLAN").unwrap().ref_type, RefType::Overlay);
|
||||
assert_eq!(
|
||||
app.xref_manager
|
||||
.entries
|
||||
.iter()
|
||||
.find(|e| e.name == "PLAN")
|
||||
.unwrap()
|
||||
.ref_type,
|
||||
RefType::Overlay
|
||||
);
|
||||
let start = app.command_line.history.len();
|
||||
let _ = app.update(Message::XrefRowOp(idx, XrefPaletteOp::Pathtype(Pathtype::None)));
|
||||
let _ = app.update(Message::XrefRowOp(
|
||||
idx,
|
||||
XrefPaletteOp::Pathtype(Pathtype::None),
|
||||
));
|
||||
let out = palette_output(&app, start);
|
||||
assert!(out.contains("PLAN"), "got: {out:?}");
|
||||
let br = app.tabs[i].scene.document.block_records.get("PLAN").unwrap();
|
||||
assert_eq!(br.xref_path, "plan.dwg", "Remove Path strips to the bare filename");
|
||||
let br = app.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.block_records
|
||||
.get("PLAN")
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
br.xref_path, "plan.dwg",
|
||||
"Remove Path strips to the bare filename"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1639,9 +1713,21 @@ mod tests {
|
||||
let start = app.command_line.history.len();
|
||||
app.xref_manager_reload_all();
|
||||
let out = palette_output(&app, start);
|
||||
assert!(out.contains("PLAN"), "reload-all must report the reference, got: {out:?}");
|
||||
let entry = app.xref_manager.entries.iter().find(|e| e.name == "PLAN").expect("PLAN listed");
|
||||
assert_eq!(entry.status, crate::io::xref_model::RefStatus::Loaded, "PLAN must resolve Loaded");
|
||||
assert!(
|
||||
out.contains("PLAN"),
|
||||
"reload-all must report the reference, got: {out:?}"
|
||||
);
|
||||
let entry = app
|
||||
.xref_manager
|
||||
.entries
|
||||
.iter()
|
||||
.find(|e| e.name == "PLAN")
|
||||
.expect("PLAN listed");
|
||||
assert_eq!(
|
||||
entry.status,
|
||||
crate::io::xref_model::RefStatus::Loaded,
|
||||
"PLAN must resolve Loaded"
|
||||
);
|
||||
std::fs::remove_dir_all(&dir).ok();
|
||||
}
|
||||
|
||||
@@ -1659,8 +1745,8 @@ mod tests {
|
||||
fn palette_unload_nested_reports_per_entry() {
|
||||
// F6: palette Unload on a nested row reports the per-entry nested
|
||||
// error (CLI wording) instead of the confusing 'no loaded reference'.
|
||||
use codec::tables::BlockRecord;
|
||||
use crate::ui::window::xref_manager::XrefPaletteOp;
|
||||
use codec::tables::BlockRecord;
|
||||
let dir = palette_tmpdir("nested");
|
||||
let mut host_doc = codec::CadDocument::new();
|
||||
let mut inner = BlockRecord::new("INNER");
|
||||
@@ -1678,7 +1764,12 @@ mod tests {
|
||||
app.tabs[i].scene.document.block_records.add(br).unwrap();
|
||||
app.tabs[i].current_path = Some(dir.join("app.dwg"));
|
||||
app.refresh_xref_manager();
|
||||
let idx = app.xref_manager.entries.iter().position(|e| e.name == "INNER").expect("nested INNER listed");
|
||||
let idx = app
|
||||
.xref_manager
|
||||
.entries
|
||||
.iter()
|
||||
.position(|e| e.name == "INNER")
|
||||
.expect("nested INNER listed");
|
||||
assert!(app.xref_manager.entries[idx].parent_key.is_some());
|
||||
app.xref_manager.selected.insert(idx);
|
||||
let start = app.command_line.history.len();
|
||||
@@ -1694,27 +1785,36 @@ mod tests {
|
||||
// F7: palette Reload on an image/PDF row reports the drawing-only
|
||||
// error and leaves its unloaded flag untouched (no spurious
|
||||
// no-match after a flag clear).
|
||||
use codec::objects::{ImageDefinition, ObjectType};
|
||||
use crate::io::xref_model::RefKind;
|
||||
use crate::ui::window::xref_manager::XrefPaletteOp;
|
||||
use codec::objects::{ImageDefinition, ObjectType};
|
||||
let dir = palette_tmpdir("imgreload");
|
||||
let mut app = fresh();
|
||||
let i = app.active_tab;
|
||||
let h = app.tabs[i].scene.document.allocate_handle();
|
||||
let mut def = ImageDefinition::with_dimensions("img.png", 8, 8);
|
||||
def.handle = h;
|
||||
app.tabs[i].scene.document.objects.insert(h, ObjectType::ImageDefinition(def));
|
||||
let mut img = codec::entities::RasterImage::new(
|
||||
"img.png",
|
||||
codec::types::Vector3::ZERO,
|
||||
8.0,
|
||||
8.0,
|
||||
);
|
||||
app.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.objects
|
||||
.insert(h, ObjectType::ImageDefinition(def));
|
||||
let mut img =
|
||||
codec::entities::RasterImage::new("img.png", codec::types::Vector3::ZERO, 8.0, 8.0);
|
||||
img.definition_handle = Some(h);
|
||||
app.tabs[i].scene.document.add_entity(codec::EntityType::RasterImage(img)).unwrap();
|
||||
app.tabs[i]
|
||||
.scene
|
||||
.document
|
||||
.add_entity(codec::EntityType::RasterImage(img))
|
||||
.unwrap();
|
||||
app.tabs[i].current_path = Some(dir.join("host.dwg"));
|
||||
app.refresh_xref_manager();
|
||||
let idx = app.xref_manager.entries.iter().position(|e| e.kind == RefKind::Image).expect("image listed");
|
||||
let idx = app
|
||||
.xref_manager
|
||||
.entries
|
||||
.iter()
|
||||
.position(|e| e.kind == RefKind::Image)
|
||||
.expect("image listed");
|
||||
let key = app.xref_manager.entries[idx].key;
|
||||
app.xref_manager.selected.insert(idx);
|
||||
app.tabs[i].xref_unloaded.add(key);
|
||||
@@ -1723,7 +1823,10 @@ mod tests {
|
||||
let out = palette_output(&app, start);
|
||||
assert!(out.contains("img.png"), "got: {out:?}");
|
||||
assert_eq!(app.command_line.history.len(), start + 1);
|
||||
assert!(app.tabs[i].xref_unloaded.is_unloaded(key), "image flag must stay untouched");
|
||||
assert!(
|
||||
app.tabs[i].xref_unloaded.is_unloaded(key),
|
||||
"image flag must stay untouched"
|
||||
);
|
||||
std::fs::remove_dir_all(&dir).ok();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user