forked from 1b-agent/opencadstudio-upstream
feat(ui): render BPT popup and authoring selection state
This commit is contained in:
1 parent
286bdf6426
commit
29d903d5d2
2 files changed
+116
-20
No files matched your search
+68
-11
@@ -1114,8 +1114,14 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
);
|
||||
let point = tab.scene.camera.borrow().project(location, vp_bounds)?;
|
||||
let point = iced::Point::new(vp_bounds.x + point.x, vp_bounds.y + point.y);
|
||||
(point.x.is_finite() && point.y.is_finite())
|
||||
.then(|| (point, parameter.name.clone(), vp_bounds))
|
||||
(point.x.is_finite() && point.y.is_finite()).then(|| {
|
||||
(
|
||||
point,
|
||||
parameter.name.clone(),
|
||||
vp_bounds,
|
||||
tab.selected_authoring == Some(parameter.handle),
|
||||
)
|
||||
})
|
||||
});
|
||||
let authoring_points =
|
||||
tab.active_block_edit_session()
|
||||
@@ -1125,7 +1131,7 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
session.br_handle,
|
||||
)
|
||||
.into_iter()
|
||||
.filter_map(|(_, parameter)| {
|
||||
.filter_map(|(handle, parameter)| {
|
||||
let project = |point: codec::types::Vector3| {
|
||||
let point = tab.scene.camera.borrow().project(
|
||||
glam::DVec3::new(point.x, point.y, point.z),
|
||||
@@ -1140,6 +1146,7 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
project(parameter.definition_label_point)?,
|
||||
parameter.position_name.clone(),
|
||||
vp_bounds,
|
||||
tab.selected_authoring == Some(handle),
|
||||
))
|
||||
})
|
||||
.collect()
|
||||
@@ -1153,8 +1160,9 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
session.br_handle,
|
||||
)
|
||||
.iter()
|
||||
.map(|p| {
|
||||
.map(|p| {
|
||||
(
|
||||
p.handle,
|
||||
crate::scene::block_distance_parameter::graphic(p),
|
||||
p.native.definition_base_point,
|
||||
)
|
||||
@@ -1167,6 +1175,7 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
.iter()
|
||||
.map(|p| {
|
||||
(
|
||||
p.handle,
|
||||
crate::scene::block_orientation_parameter::graphic(p),
|
||||
crate::scene::block_orientation_parameter::marker_tail(p),
|
||||
)
|
||||
@@ -1177,10 +1186,29 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
&tab.scene.document,
|
||||
session.br_handle,
|
||||
)
|
||||
.map(|(_, p)| {
|
||||
.map(|(handle, p)| (handle, p.parameter.definition_point))
|
||||
.or_else(|| {
|
||||
let name = tab
|
||||
.scene
|
||||
.document
|
||||
.block_records
|
||||
.iter()
|
||||
.find(|record| record.handle == session.br_handle)?
|
||||
.name
|
||||
.as_str();
|
||||
Some((
|
||||
session.br_handle,
|
||||
crate::scene::render_graph::block_base_point(
|
||||
&tab.scene.document,
|
||||
name,
|
||||
),
|
||||
))
|
||||
})
|
||||
.map(|(handle, point)| {
|
||||
let mut g = crate::scene::block_distance_parameter::Graphic::default();
|
||||
g.base_grips.push(p.parameter.definition_point);
|
||||
(g, p.parameter.definition_point)
|
||||
g.base_grips.push(point);
|
||||
g.labels.push((point, "Basepoint".into()));
|
||||
(handle, g, point)
|
||||
}),
|
||||
)
|
||||
.chain(
|
||||
@@ -1189,12 +1217,12 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
session.br_handle,
|
||||
)
|
||||
.into_iter()
|
||||
.map(|(_, p)| {
|
||||
.map(|(handle, p)| {
|
||||
let mut g = crate::scene::block_distance_parameter::Graphic::default();
|
||||
g.lookup_grips.push(p.parameter.definition_point);
|
||||
g.labels
|
||||
.push((p.parameter.definition_point, p.lookup_name.clone()));
|
||||
(g, p.parameter.definition_point)
|
||||
(handle, g, p.parameter.definition_point)
|
||||
}),
|
||||
)
|
||||
.chain(
|
||||
@@ -1219,10 +1247,10 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
g.grips.push((action.display_location, false));
|
||||
g.labels
|
||||
.push((action.display_location, action.element.name.clone()));
|
||||
(g, action.display_location)
|
||||
(handle, g, action.display_location)
|
||||
}),
|
||||
)
|
||||
.filter_map(|(graphic, marker_tail)| {
|
||||
.filter_map(|(handle, graphic, marker_tail)| {
|
||||
let project = |p: codec::types::Vector3| {
|
||||
let p = tab
|
||||
.scene
|
||||
@@ -1257,6 +1285,7 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
})
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
Some(crate::ui::overlay::AuthoringDimension {
|
||||
selected: tab.selected_authoring == Some(handle),
|
||||
lines,
|
||||
base_grips: graphic
|
||||
.base_grips
|
||||
@@ -2052,6 +2081,34 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
viewport_stack.push(position_canvas_overlay(anchor, panel.into()));
|
||||
}
|
||||
}
|
||||
if let Some(popup) = self.table_popup.as_ref() {
|
||||
if !tab.is_start {
|
||||
let mut col = column![text(popup.header.clone()).size(12)].spacing(2);
|
||||
for (idx, name) in popup.rows.iter().enumerate() {
|
||||
let mark: Element<'_, Message> = if popup.current == Some(idx) {
|
||||
crate::ui::icons::themed_check_cell(true)
|
||||
} else {
|
||||
Space::new().width(11).into()
|
||||
};
|
||||
col = col.push(
|
||||
button(
|
||||
row![container(mark).width(16), text(name).size(12)]
|
||||
.spacing(2)
|
||||
.align_y(iced::Center),
|
||||
)
|
||||
.on_press(Message::TableRowPick(idx))
|
||||
.padding([3, 10])
|
||||
.width(Fill),
|
||||
);
|
||||
}
|
||||
let panel =
|
||||
container(iced::widget::scrollable(col).height(iced::Length::Shrink))
|
||||
.padding(2);
|
||||
let anchor = iced::Point::new(popup.anchor.x + 12.0, popup.anchor.y + 12.0);
|
||||
viewport_stack =
|
||||
viewport_stack.push(position_canvas_overlay(anchor, panel.into()));
|
||||
}
|
||||
}
|
||||
|
||||
// Selection actions: with only PDF underlays or only xrefs
|
||||
// selected, their tools take the right edge (over the paper-space
|
||||
|
||||
+48
-9
@@ -1037,8 +1037,8 @@ pub(crate) fn selection_overlay<'a>(
|
||||
constraint_glyph_selected: Arc<[bool]>,
|
||||
constraint_glyph_tooltip: Option<String>,
|
||||
constraint_cursor_badge: Option<String>,
|
||||
authoring_visibility: Option<(Point, String, iced::Rectangle)>,
|
||||
authoring_points: Vec<(Point, Point, String, iced::Rectangle)>,
|
||||
authoring_visibility: Option<(Point, String, iced::Rectangle, bool)>,
|
||||
authoring_points: Vec<(Point, Point, String, iced::Rectangle, bool)>,
|
||||
authoring_dimensions: Vec<AuthoringDimension>,
|
||||
) -> Element<'a, Message> {
|
||||
canvas(SelectionCanvas {
|
||||
@@ -1079,6 +1079,7 @@ pub(crate) fn selection_overlay<'a>(
|
||||
}
|
||||
|
||||
pub(crate) struct AuthoringDimension {
|
||||
pub selected: bool,
|
||||
pub lines: Vec<[Point; 2]>,
|
||||
pub round_grips: Vec<Point>,
|
||||
pub base_grips: Vec<Point>,
|
||||
@@ -1160,8 +1161,8 @@ struct SelectionCanvas {
|
||||
/// Symbol shown beside the cursor while it targets an entity that already
|
||||
/// participates in an enabled geometric constraint.
|
||||
constraint_cursor_badge: Option<String>,
|
||||
authoring_visibility: Option<(Point, String, iced::Rectangle)>,
|
||||
authoring_points: Vec<(Point, Point, String, iced::Rectangle)>,
|
||||
authoring_visibility: Option<(Point, String, iced::Rectangle, bool)>,
|
||||
authoring_points: Vec<(Point, Point, String, iced::Rectangle, bool)>,
|
||||
authoring_dimensions: Vec<AuthoringDimension>,
|
||||
}
|
||||
|
||||
@@ -2388,15 +2389,25 @@ impl canvas::Program<Message> for SelectionCanvas {
|
||||
frame.stroke(&b1, stroke.clone());
|
||||
frame.stroke(&b2, stroke);
|
||||
}
|
||||
if let Some((point, label, clip)) = &self.authoring_visibility {
|
||||
if let Some((point, label, clip, selected)) = &self.authoring_visibility {
|
||||
frame.with_clip(*clip, |frame| {
|
||||
let color = theme.palette().primary.base.color;
|
||||
let color = if *selected {
|
||||
theme.palette().primary.strong.color
|
||||
} else {
|
||||
theme.palette().primary.base.color
|
||||
};
|
||||
let triangle = canvas::Path::new(|builder| {
|
||||
builder.move_to(Point::new(point.x - 5.0, point.y - 3.0));
|
||||
builder.line_to(Point::new(point.x + 5.0, point.y - 3.0));
|
||||
builder.line_to(Point::new(point.x, point.y + 5.0));
|
||||
builder.close();
|
||||
});
|
||||
if *selected {
|
||||
frame.stroke(
|
||||
&canvas::Path::circle(*point, 10.0),
|
||||
canvas::Stroke::default().with_color(color).with_width(2.0),
|
||||
);
|
||||
}
|
||||
frame.fill(&triangle, color);
|
||||
frame.fill_text(canvas::Text {
|
||||
content: label.clone(),
|
||||
@@ -2407,9 +2418,19 @@ impl canvas::Program<Message> for SelectionCanvas {
|
||||
});
|
||||
});
|
||||
}
|
||||
for (point, label_point, label, clip) in &self.authoring_points {
|
||||
for (point, label_point, label, clip, selected) in &self.authoring_points {
|
||||
frame.with_clip(*clip, |frame| {
|
||||
let color = theme.palette().primary.base.color;
|
||||
let color = if *selected {
|
||||
theme.palette().primary.strong.color
|
||||
} else {
|
||||
theme.palette().primary.base.color
|
||||
};
|
||||
if *selected {
|
||||
frame.stroke(
|
||||
&canvas::Path::circle(*point, 10.0),
|
||||
canvas::Stroke::default().with_color(color).with_width(2.0),
|
||||
);
|
||||
}
|
||||
frame.stroke(
|
||||
&canvas::Path::line(*point, *label_point),
|
||||
canvas::Stroke::default().with_color(color),
|
||||
@@ -2432,7 +2453,25 @@ impl canvas::Program<Message> for SelectionCanvas {
|
||||
}
|
||||
for dimension in &self.authoring_dimensions {
|
||||
frame.with_clip(dimension.clip, |frame| {
|
||||
let color = theme.palette().primary.base.color;
|
||||
let color = if dimension.selected {
|
||||
theme.palette().primary.strong.color
|
||||
} else {
|
||||
theme.palette().primary.base.color
|
||||
};
|
||||
if dimension.selected {
|
||||
for point in dimension
|
||||
.base_grips
|
||||
.iter()
|
||||
.chain(dimension.lookup_grips.iter())
|
||||
.chain(dimension.round_grips.iter())
|
||||
.chain(dimension.grips.iter().map(|(point, _)| point))
|
||||
{
|
||||
frame.stroke(
|
||||
&canvas::Path::circle(*point, 10.0),
|
||||
canvas::Stroke::default().with_color(color).with_width(2.0),
|
||||
);
|
||||
}
|
||||
}
|
||||
for [a, b] in &dimension.lines {
|
||||
frame.stroke(
|
||||
&canvas::Path::line(*a, *b),
|
||||
|
||||
Reference in new issue
Block a user