forked from 1b-agent/opencadstudio-upstream
Count: measured messages and listing, groups, Current area, boundary checks, fills and solids recoloured
- COUNTCOLOR / COUNTERRORCOLOR / COUNTSERVICE reject any other value with the range message; COUNTTABLE ? lists in the reference order, padded, 22 lines a page with Press ENTER to continue:, then the totals. - Target picks report N found / N found, M total; several objects (or one that is not a block reference) count their copies, shown as Geometries in the palette. - Current area is the area in use (kept aside by Entire model space), otherwise all of model space; an invalid Object boundary ends with the reference message. - Count colours reach solids and fills; the palette list and the count are recomputed only when the drawing changes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
d830e40bfa
commit
0a26709d13
31 files changed
+214
-60
No files matched your search
@@ -33,7 +33,8 @@ pub enum CountTarget {
|
||||
matching: [bool; 3],
|
||||
picked: bool,
|
||||
},
|
||||
/// Several picked objects counted as one group.
|
||||
/// Picked objects (several, or one that is not a reference): the copies
|
||||
/// of the group are counted.
|
||||
Group(Vec<Handle>),
|
||||
}
|
||||
|
||||
@@ -50,6 +51,10 @@ pub struct CountMode {
|
||||
pub cursor: Option<usize>,
|
||||
/// The scene geometry epoch the colouring was computed at.
|
||||
pub epoch: u64,
|
||||
/// The area Entire model space set aside, for a later Current area.
|
||||
pub remembered: Option<(Vec<[f64; 2]>, Option<(Handle, bool)>)>,
|
||||
/// The result and count at `epoch` (recomputed when the drawing changes).
|
||||
pub cache: Option<(CountResult, usize)>,
|
||||
}
|
||||
|
||||
/// A count mode's result: the counted references and the overlapping
|
||||
@@ -80,13 +85,35 @@ impl CountMode {
|
||||
}
|
||||
|
||||
pub fn result(&self, doc: &CadDocument) -> CountResult {
|
||||
match &self.cache {
|
||||
Some((result, _)) => result.clone(),
|
||||
None => self.compute(doc).0,
|
||||
}
|
||||
}
|
||||
|
||||
/// What the count shows: the counted references, or the copies of a group.
|
||||
pub fn count(&self, doc: &CadDocument) -> usize {
|
||||
match &self.cache {
|
||||
Some((_, n)) => *n,
|
||||
None => self.compute(doc).1,
|
||||
}
|
||||
}
|
||||
|
||||
/// The result and the count, worked out from the drawing.
|
||||
pub fn compute(&self, doc: &CadDocument) -> (CountResult, usize) {
|
||||
if let Some(CountTarget::Group(handles)) = &self.target {
|
||||
let groups = codec::count::group_matches(doc, handles, self.area.as_deref());
|
||||
let result = CountResult { counted: groups.concat(), errors: Vec::new(), overlapped: Vec::new() };
|
||||
return (result, groups.len());
|
||||
}
|
||||
let result = self.block_result(doc);
|
||||
let n = result.counted.len();
|
||||
(result, n)
|
||||
}
|
||||
|
||||
fn block_result(&self, doc: &CadDocument) -> CountResult {
|
||||
match &self.target {
|
||||
None => CountResult::default(),
|
||||
Some(CountTarget::Group(handles)) => CountResult {
|
||||
counted: handles.iter().copied().filter(|h| doc.get_entity(*h).is_some()).collect(),
|
||||
errors: Vec::new(),
|
||||
overlapped: Vec::new(),
|
||||
},
|
||||
None | Some(CountTarget::Group(_)) => CountResult::default(),
|
||||
Some(CountTarget::Block { name, .. }) => {
|
||||
let instances = self.instances(doc);
|
||||
let key = self.key(&instances);
|
||||
@@ -100,15 +127,6 @@ impl CountMode {
|
||||
}
|
||||
}
|
||||
|
||||
/// What the count shows: the counted references, or 1 for a group whose
|
||||
/// objects all exist.
|
||||
pub fn count(&self, doc: &CadDocument) -> usize {
|
||||
match &self.target {
|
||||
Some(CountTarget::Group(handles)) => usize::from(handles.iter().all(|h| doc.get_entity(*h).is_some())),
|
||||
_ => self.result(doc).counted.len(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The name the toolbar and the command line show for the target.
|
||||
pub fn target_name(&self) -> Option<String> {
|
||||
match &self.target {
|
||||
@@ -137,6 +155,8 @@ pub struct CountPalette {
|
||||
pub color: i16,
|
||||
pub error_color: i16,
|
||||
pub service: bool,
|
||||
/// The list's references for (document, geometry epoch, area).
|
||||
pub list_cache: std::cell::RefCell<Option<(usize, u64, Option<Vec<[f64; 2]>>, std::rc::Rc<Vec<BlockInstance>>)>>,
|
||||
}
|
||||
|
||||
impl Default for CountPalette {
|
||||
@@ -153,6 +173,7 @@ impl Default for CountPalette {
|
||||
color: 3,
|
||||
error_color: 1,
|
||||
service: true,
|
||||
list_cache: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -434,7 +455,12 @@ fn mode_view<'a>(palette: &'a CountPalette, mode: &'a CountMode, doc: &CadDocume
|
||||
let mut details = column![button(
|
||||
row![
|
||||
crate::ui::icons::themed_success(CHECK_ICON, 12.0),
|
||||
text(format!("{name}: {}", mode.count(doc))).size(12).width(Fill),
|
||||
text(match mode.target {
|
||||
Some(CountTarget::Group(_)) => crate::tf!("Geometries: {}", mode.count(doc)).into_owned(),
|
||||
_ => format!("{name}: {}", mode.count(doc)),
|
||||
})
|
||||
.size(12)
|
||||
.width(Fill),
|
||||
]
|
||||
.spacing(6)
|
||||
.align_y(iced::Center),
|
||||
@@ -488,16 +514,25 @@ pub fn view<'a>(
|
||||
palette: &'a CountPalette,
|
||||
mode: Option<&'a CountMode>,
|
||||
doc: &'a CadDocument,
|
||||
epoch: u64,
|
||||
width: f32,
|
||||
auto_collapse: bool,
|
||||
) -> Element<'a, Message> {
|
||||
let title_bar = crate::ui::dock::title_bar(PanelId::Count, crate::t!("Count palette").into_owned(), auto_collapse);
|
||||
// ponytail: the list is recounted on every view; cache by geometry epoch
|
||||
// if very large drawings make the palette slow.
|
||||
let body = match mode {
|
||||
Some(mode) if mode.target.is_some() => mode_view(palette, mode, doc),
|
||||
_ => {
|
||||
let instances = codec::count::block_instances(doc, mode.and_then(|m| m.area.as_deref()));
|
||||
let area = mode.and_then(|m| m.area.clone());
|
||||
let key = (doc as *const CadDocument as usize, epoch);
|
||||
let mut cache = palette.list_cache.borrow_mut();
|
||||
let instances = match cache.as_ref() {
|
||||
Some((d, e, a, list)) if (*d, *e) == key && *a == area => list.clone(),
|
||||
_ => {
|
||||
let list = std::rc::Rc::new(codec::count::block_instances(doc, area.as_deref()));
|
||||
*cache = Some((key.0, key.1, area, list.clone()));
|
||||
list
|
||||
}
|
||||
};
|
||||
list_view(palette, &instances)
|
||||
}
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user