Files
ARCADIA-Studio/crates/oa-desktop/src/diagram_usage/view.rs
T

221 lines
7.1 KiB
Rust

use super::*;
use crate::{
app::{App, Message},
style,
views::{action, short},
};
use iced::{
Element, Fill,
widget::{self, column, container, row, text, text_input, tooltip},
};
use std::collections::BTreeSet;
const PAGE_SIZE: usize = 6;
pub(crate) fn overlay<'a>(app: &'a App, base: Element<'a, Message>) -> Element<'a, Message> {
let Some(panel) = &app.diagram_usages else {
return base;
};
let p = app.project();
let token = panel.token;
let message = |event| Message::DiagramUsage(event);
let matched = panel.matches(p);
let mut surfaces = Vec::new();
let mut seen = BTreeSet::new();
for usage in &matched {
if seen.insert(usage.surface) {
surfaces.push(usage.surface);
}
}
let targets: Vec<_> = matched
.iter()
.copied()
.filter(|usage| Some(usage.surface) == panel.destination)
.collect();
let count = if panel.destination.is_some() {
targets.len()
} else {
surfaces.len()
};
let last = count.saturating_sub(1) / PAGE_SIZE;
let page = panel.page.min(last);
let total_surfaces = panel
.usages
.iter()
.map(|u| u.surface)
.collect::<BTreeSet<_>>()
.len();
let mut content = column![
row![
text("Show in diagrams").size(22).width(Fill),
action("Close", message(Event::Close(token)))
]
.spacing(12),
tooltip(
text(format!(
"{} · @{}",
short(p.named(panel.context.subject), 48),
short(alias(p, panel.context.subject), 48)
))
.size(14),
container(
widget::scrollable(
text(format!(
"{}\n@{}",
p.named(panel.context.subject),
alias(p, panel.context.subject)
))
.size(13)
)
.height(220)
)
.padding(10)
.width(620)
.style(style::card),
tooltip::Position::Bottom
),
text(if panel.loading {
"Searching rendered objects…".into()
} else {
format!(
"{} diagram destinations · {} representations",
total_surfaces,
panel.usages.len()
)
})
.size(12)
.color(style::MUTED),
text_input("Filter diagram, occurrence, or alias", &panel.search)
.id(format!("diagram-usage-filter-{}", panel.token))
.padding(9)
.on_input(move |value| Message::DiagramUsage(Event::Search(token, value)))
.on_submit(message(Event::Activate(token))),
]
.spacing(10);
if let Some(notice) = &panel.notice {
content = content.push(text(notice).size(13));
}
if let Some(surface) = panel.destination {
content = content.push(
row![
action("All diagrams", message(Event::Destination(token, None))),
text(short(p.named(surface.id()), 55)).size(15),
]
.spacing(10),
);
for (index, usage) in targets
.into_iter()
.enumerate()
.skip(page * PAGE_SIZE)
.take(PAGE_SIZE)
{
let name = target_name(p, usage);
content = content.push(tooltip(
action(
&format!("{} · {}", usage.role, short(&name, 70)),
message(Event::Choose(token, usage.clone())),
)
.width(Fill)
.style(if panel.cursor == index {
style::selected
} else {
style::nav
}),
container(text(name).size(13))
.padding(10)
.max_width(680)
.style(style::card),
tooltip::Position::Top,
));
}
} else {
for (index, surface) in surfaces
.into_iter()
.enumerate()
.skip(page * PAGE_SIZE)
.take(PAGE_SIZE)
{
let targets = matched.iter().filter(|u| u.surface == surface).count();
let name = format!(
"{} · {} (@{}) · {} representations",
surface.category(p),
p.named(surface.id()),
alias(p, surface.id()),
targets
);
let layer = p
.diagrams
.get(&surface.id())
.map(|d| d.layer)
.or_else(|| p.layer_of(surface.id()))
.map(|l| l.to_string())
.unwrap_or_default();
content = content.push(tooltip(
action(
&format!(
"{} · {} · {} · {}",
surface.category(p),
layer,
short(p.named(surface.id()), 34),
targets
),
message(Event::Destination(token, Some(surface))),
)
.width(Fill)
.style(if panel.cursor == index {
style::selected
} else {
style::nav
}),
container(text(name).size(13))
.padding(10)
.max_width(680)
.style(style::card),
tooltip::Position::Top,
));
}
}
if panel.loading {
content = content.push(text("Finding diagram representations…").size(13));
} else if count == 0 {
content = content.push(text(if panel.usages.is_empty() {
"No currently rendered representation found. Folded or filtered objects and unexpanded reuse contents are excluded."
} else { "No results match this filter." }).size(13));
}
let mut paging = row![
text(format!(
"Page {} of {} · {} matches",
page + 1,
last + 1,
count
))
.size(12)
.width(Fill)
]
.spacing(8);
if page > 0 {
paging = paging.push(action("Previous", message(Event::Page(token, page - 1))));
}
if page < last {
paging = paging.push(action("Next", message(Event::Page(token, page + 1))));
}
content = content.push(paging).push(text("↑ ↓ choose · Enter opens · Escape closes. Source and saved view settings are preserved.").size(12).color(style::MUTED));
widget::stack![
base,
widget::opaque(
container(
container(content)
.padding(22)
.width((app.window_size.width - 80.).clamp(620., 820.))
.style(style::card)
)
.center(Fill)
.style(|_| container::Style {
background: Some(iced::Color::from_rgba(0.08, 0.12, 0.18, 0.38).into()),
..Default::default()
})
)
]
.into()
}