forked from 1b-agent/opencadstudio-upstream
feat(grip): multi-functional hover popup menu
Phase 2 of the grip overhaul: when the cursor dwells on a selected entity's grip the overlay opens a popup menu with entity-specific options (Stretch / Add Vertex / Remove Vertex / Convert to Arc-Line / …). Picking an item dispatches `apply_grip_menu`; the default `Stretch` entry is a no-op that lets the user click the grip to start the normal drag. - `GripMenuItem` + `GripMenuAction` (full vocabulary covering stretch, add/remove vertex, convert to arc/line, reverse arrows, text-position variants, hatch parameters, tangent direction). - `Grippable` trait gains `grip_menu` + `apply_grip_menu` with trait-default `Stretch`-only impls so every existing entity gets the popup for free. - `EntityTypeOps` dispatches both methods across the same entity list as the existing grip / property machinery. - `OpenCADStudio` carries `grip_hover` (dwell tracker) + `grip_popup` (open menu). `update_grip_hover` runs from `ViewportMove`: hit-tests grips, refreshes the dwell timer, and opens the popup after 600 ms. Cursor drift past 80 px or a grip click dismisses it. - `view.rs` paints the popup as an absolute-positioned column of buttons at the grip's screen anchor; each button publishes `Message::GripMenuPick(idx)`. - `LwPolyline` overrides `Grippable` manually (skips the standard macro) so its vertex grip exposes Add/Remove Vertex and its segment-midpoint grip exposes Add Vertex + Convert to Arc/Line. `apply_grip_menu` performs the edits: vertex insertion at the chord midpoint inheriting the previous bulge, vertex removal, and bulge toggle for the arc/line conversion.
This commit is contained in:
1 parent
5755c2e130
commit
6c1462932d
6 files changed
+443
-2
No files matched your search
+50
-1
@@ -2,7 +2,9 @@ use acadrust::{CadDocument, EntityType};
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::scene::acad_to_truck::TruckEntity;
|
||||
use crate::scene::object::{GripApply, GripDef, PropSection};
|
||||
use crate::scene::object::{
|
||||
GripApply, GripDef, GripMenuAction, GripMenuItem, PropSection,
|
||||
};
|
||||
use crate::scene::tess_util::FallbackGeometry;
|
||||
|
||||
pub trait TruckConvertible {
|
||||
@@ -20,6 +22,19 @@ pub trait FallbackTess {
|
||||
pub trait Grippable {
|
||||
fn grips(&self) -> Vec<GripDef>;
|
||||
fn apply_grip(&mut self, grip_id: usize, apply: GripApply);
|
||||
/// Items shown in the hover popup that opens when the cursor
|
||||
/// dwells on a grip. Default is a single `Stretch` entry — i.e.
|
||||
/// the popup just confirms the default drag behaviour. Override
|
||||
/// per entity to add Add Vertex / Convert to Arc / Reverse Arrows /
|
||||
/// etc.
|
||||
fn grip_menu(&self, _grip_id: usize) -> Vec<GripMenuItem> {
|
||||
vec![GripMenuItem { label: "Stretch", action: GripMenuAction::Stretch }]
|
||||
}
|
||||
/// React to a popup-menu commit. Default no-op — `Stretch` is the
|
||||
/// "do nothing extra" path, the normal drag still happens on click.
|
||||
/// Entities override this to mutate themselves when the user picks
|
||||
/// Add Vertex / Remove Vertex / Convert / Reverse / …
|
||||
fn apply_grip_menu(&mut self, _grip_id: usize, _action: GripMenuAction) {}
|
||||
}
|
||||
|
||||
pub trait PropertyEditable {
|
||||
@@ -58,9 +73,11 @@ pub trait TextContent {
|
||||
pub trait EntityTypeOps {
|
||||
fn to_truck_entity(&self, document: &CadDocument) -> Option<TruckEntity>;
|
||||
fn grips(&self) -> Vec<GripDef>;
|
||||
fn grip_menu(&self, grip_id: usize) -> Vec<GripMenuItem>;
|
||||
fn geometry_properties(&self, text_style_names: &[String]) -> Option<PropSection>;
|
||||
fn apply_geom_prop(&mut self, field: &str, value: &str);
|
||||
fn apply_grip(&mut self, grip_id: usize, apply: GripApply);
|
||||
fn apply_grip_menu(&mut self, grip_id: usize, action: GripMenuAction);
|
||||
fn apply_transform(&mut self, t: &EntityTransform);
|
||||
fn mass_props(&self) -> Option<MassProps>;
|
||||
fn text_content(&self) -> Option<String>;
|
||||
@@ -238,6 +255,38 @@ impl EntityTypeOps for EntityType {
|
||||
)
|
||||
}
|
||||
|
||||
fn grip_menu(&self, grip_id: usize) -> Vec<GripMenuItem> {
|
||||
dispatch!(self,
|
||||
|e| Grippable::grip_menu(e, grip_id),
|
||||
[
|
||||
Line, Circle, Arc, Ellipse, LwPolyline, Polyline, Polyline2D,
|
||||
Polyline3D, Ray, XLine, RasterImage, Wipeout,
|
||||
AttributeDefinition, AttributeEntity, MLine, Tolerance,
|
||||
Solid, Solid3D, Region, Body, Face3D, PolygonMesh,
|
||||
PolyfaceMesh, Mesh, Table, Point, Spline, Text, MText,
|
||||
Viewport, Insert, Leader, MultiLeader, Dimension, Hatch,
|
||||
Underlay, Shape, Ole2Frame,
|
||||
],
|
||||
_ => vec![],
|
||||
)
|
||||
}
|
||||
|
||||
fn apply_grip_menu(&mut self, grip_id: usize, action: GripMenuAction) {
|
||||
dispatch!(self,
|
||||
|e| Grippable::apply_grip_menu(e, grip_id, action),
|
||||
[
|
||||
Line, Circle, Arc, Ellipse, LwPolyline, Polyline, Polyline2D,
|
||||
Polyline3D, Ray, XLine, RasterImage, Wipeout,
|
||||
AttributeDefinition, AttributeEntity, MLine, Tolerance,
|
||||
Solid, Solid3D, Region, Body, Face3D, PolygonMesh,
|
||||
PolyfaceMesh, Mesh, Table, Point, Spline, Text, MText,
|
||||
Viewport, Insert, Leader, MultiLeader, Dimension, Hatch,
|
||||
Underlay, Shape, Ole2Frame,
|
||||
],
|
||||
_ => {},
|
||||
)
|
||||
}
|
||||
|
||||
fn apply_transform(&mut self, t: &EntityTransform) {
|
||||
dispatch!(self,
|
||||
|e| Transformable::apply_transform(e, t),
|
||||
|
||||
Reference in new issue
Block a user