forked from 1b-agent/opencadstudio-upstream
fix(layer-state): share linetype list via Arc instead of cloning per row
editor_layer_row and view_editor took Vec<String>, cloning N strings per row per frame (times two build-closure runs). Both take Arc<[String]> now; a plain borrow cannot cross the twice-run closure (E0373), hence the Arc. Cow empty-filter short-circuit for both search queries. Test: view_editor_accepts_shared_linetypes (RED first). Full suite: 2029 passed / 0 failed / 25 ignored, zero warnings.
This commit is contained in:
1 parent
9f9c621871
commit
15cfabdb0f
2 files changed
+62
-16
No files matched your search
+16
-8
@@ -674,18 +674,26 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
linetypes.sort_by_key(|name| name.to_lowercase());
|
||||
// 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,
|
||||
|flow| {
|
||||
crate::ui::window::layer_state_manager::view_editor(
|
||||
state,
|
||||
&self.layer_state_edit_filter,
|
||||
self.layer_state_edit_color_open,
|
||||
linetypes.clone(),
|
||||
flow,
|
||||
)
|
||||
{
|
||||
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 {
|
||||
|
||||
@@ -116,13 +116,17 @@ pub fn view_window<'a>(
|
||||
.iter()
|
||||
.find(|state| state.name.eq_ignore_ascii_case(selected))
|
||||
});
|
||||
let query = filter.trim().to_lowercase();
|
||||
let query: Cow<str> = if filter.trim().is_empty() {
|
||||
Cow::Borrowed("")
|
||||
} else {
|
||||
Cow::Owned(filter.trim().to_lowercase())
|
||||
};
|
||||
let rows: Vec<Element<'_, Message>> = states
|
||||
.iter()
|
||||
.filter(|state| {
|
||||
query.is_empty()
|
||||
|| state.name.to_lowercase().contains(&query)
|
||||
|| state.description.to_lowercase().contains(&query)
|
||||
|| state.name.to_lowercase().contains(query.as_ref())
|
||||
|| state.description.to_lowercase().contains(query.as_ref())
|
||||
})
|
||||
.map(|state| {
|
||||
let is_selected =
|
||||
@@ -402,7 +406,7 @@ fn editor_layer_row<'a>(
|
||||
index: usize,
|
||||
layer: &'a codec::LayerStateLayer,
|
||||
color_open: bool,
|
||||
linetypes: Vec<String>,
|
||||
linetypes: std::sync::Arc<[String]>,
|
||||
) -> Element<'a, Message> {
|
||||
let current_linetype = Some(layer.line_type.clone());
|
||||
let current_lineweight = Some(LwItem(layer.line_weight));
|
||||
@@ -491,7 +495,7 @@ pub fn view_editor<'a>(
|
||||
state: &'a LayerState,
|
||||
filter: &'a str,
|
||||
color_open: Option<usize>,
|
||||
linetypes: Vec<String>,
|
||||
linetypes: std::sync::Arc<[String]>,
|
||||
sizing: crate::ui::modal::ModalSizing,
|
||||
) -> Element<'a, Message> {
|
||||
let properties = [
|
||||
@@ -517,20 +521,24 @@ pub fn view_editor<'a>(
|
||||
.iter()
|
||||
.map(|layer| layer.layer_name.clone())
|
||||
.collect();
|
||||
let query = filter.trim().to_lowercase();
|
||||
let query: Cow<str> = if filter.trim().is_empty() {
|
||||
Cow::Borrowed("")
|
||||
} else {
|
||||
Cow::Owned(filter.trim().to_lowercase())
|
||||
};
|
||||
let rows = state
|
||||
.layers
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, layer)| {
|
||||
query.is_empty() || layer.layer_name.to_lowercase().contains(&query)
|
||||
query.is_empty() || layer.layer_name.to_lowercase().contains(query.as_ref())
|
||||
})
|
||||
.fold(column![].spacing(0), |rows, (index, layer)| {
|
||||
rows.push(editor_layer_row(
|
||||
index,
|
||||
layer,
|
||||
color_open == Some(index),
|
||||
linetypes.clone(),
|
||||
std::sync::Arc::clone(&linetypes),
|
||||
))
|
||||
});
|
||||
|
||||
@@ -622,3 +630,33 @@ pub fn view_editor<'a>(
|
||||
.height(sizing.height)
|
||||
.into()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod borrowed_linetypes_tests {
|
||||
// #21 RED: view_editor must take shared ownership of the linetype list
|
||||
// (a borrow cannot cross the twice-per-frame build closure) instead of
|
||||
// cloning per row — this call fails to compile until the signatures take
|
||||
// Arc<[String]>.
|
||||
use super::view_editor;
|
||||
|
||||
#[test]
|
||||
fn view_editor_accepts_shared_linetypes() {
|
||||
let state = codec::LayerState {
|
||||
name: String::new(),
|
||||
description: String::new(),
|
||||
mask: codec::LayerStateMask::default(),
|
||||
hidden: false,
|
||||
current_layer: String::new(),
|
||||
layers: Vec::new(),
|
||||
};
|
||||
let linetypes: std::sync::Arc<[String]> =
|
||||
std::sync::Arc::from(vec!["Continuous".to_string()]);
|
||||
let sizing = crate::ui::modal::ModalSizing {
|
||||
width: iced::Length::Fixed(1180.0),
|
||||
height: iced::Length::Fixed(560.0),
|
||||
};
|
||||
let _ = view_editor(&state, "", None, std::sync::Arc::clone(&linetypes), sizing);
|
||||
// Shared ownership: the source stays usable after the call.
|
||||
assert_eq!(linetypes.len(), 1);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user