Comprehensively polish up the input hints across all tools and states (#1670)
* Add missing keyhints to most tools * Standardize hints further * Improve GRS numerical display values * Additional hints improvements * Improve Path tool hints; add Ctrl+Shift+A point deselection --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
parent
2263b0ab89
commit
9ac10cdcf8
|
|
@ -197,7 +197,8 @@ pub fn default_mapping() -> Mapping {
|
|||
entry!(KeyDown(KeyS); action_dispatch=PathToolMessage::GRS { key: KeyS }),
|
||||
entry!(PointerMove; refresh_keys=[Alt, Shift], action_dispatch=PathToolMessage::PointerMove { alt: Alt, shift: Shift }),
|
||||
entry!(KeyDown(Delete); action_dispatch=PathToolMessage::Delete),
|
||||
entry!(KeyDown(KeyA); modifiers=[Control], action_dispatch=PathToolMessage::SelectAllPoints),
|
||||
entry!(KeyDown(KeyA); modifiers=[Accel], action_dispatch=PathToolMessage::SelectAllAnchors),
|
||||
entry!(KeyDown(KeyA); modifiers=[Accel, Shift], action_dispatch=PathToolMessage::DeselectAllPoints),
|
||||
entry!(KeyDown(Backspace); action_dispatch=PathToolMessage::Delete),
|
||||
entry!(KeyUp(Lmb); action_dispatch=PathToolMessage::DragStop { shift_mirror_distance: Shift }),
|
||||
entry!(KeyDown(Enter); action_dispatch=PathToolMessage::Enter {
|
||||
|
|
@ -230,7 +231,7 @@ pub fn default_mapping() -> Mapping {
|
|||
entry!(KeyDown(ArrowDown); modifiers=[Shift, ArrowRight], action_dispatch=PathToolMessage::NudgeSelectedPoints { delta_x: BIG_NUDGE_AMOUNT, delta_y: BIG_NUDGE_AMOUNT }),
|
||||
//
|
||||
// PenToolMessage
|
||||
entry!(PointerMove; refresh_keys=[Control, Shift], action_dispatch=PenToolMessage::PointerMove { snap_angle: Shift, break_handle: Alt, lock_angle: Control}),
|
||||
entry!(PointerMove; refresh_keys=[Control, Alt, Shift], action_dispatch=PenToolMessage::PointerMove { snap_angle: Shift, break_handle: Alt, lock_angle: Control}),
|
||||
entry!(KeyDown(Lmb); action_dispatch=PenToolMessage::DragStart),
|
||||
entry!(KeyUp(Lmb); action_dispatch=PenToolMessage::DragStop),
|
||||
entry!(KeyDown(Rmb); action_dispatch=PenToolMessage::Confirm),
|
||||
|
|
@ -296,8 +297,8 @@ pub fn default_mapping() -> Mapping {
|
|||
entry!(KeyDown(KeyZ); modifiers=[Accel, Shift], action_dispatch=DocumentMessage::Redo),
|
||||
entry!(KeyDown(KeyY); modifiers=[Accel], action_dispatch=DocumentMessage::Redo),
|
||||
entry!(KeyDown(KeyZ); modifiers=[Accel], action_dispatch=DocumentMessage::Undo),
|
||||
entry!(KeyDown(KeyA); modifiers=[Accel, Shift], action_dispatch=DocumentMessage::DeselectAllLayers),
|
||||
entry!(KeyDown(KeyA); modifiers=[Accel], action_dispatch=DocumentMessage::SelectAllLayers),
|
||||
entry!(KeyDown(KeyA); modifiers=[Accel, Shift], action_dispatch=DocumentMessage::DeselectAllLayers),
|
||||
entry!(KeyDown(KeyS); modifiers=[Accel], action_dispatch=DocumentMessage::SaveDocument),
|
||||
entry!(KeyDown(KeyD); modifiers=[Accel], action_dispatch=DocumentMessage::DuplicateSelectedLayers),
|
||||
entry!(KeyDown(KeyJ); modifiers=[Accel], action_dispatch=DocumentMessage::DuplicateSelectedLayers),
|
||||
|
|
|
|||
|
|
@ -192,6 +192,8 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
|
|||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default });
|
||||
responses.add(FrontendMessage::UpdateInputHints {
|
||||
hint_data: HintData(vec![
|
||||
// TODO: Fix bug where canceling doesn't work except with the Navigate tool active
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo {
|
||||
key_groups: vec![KeysGroup(vec![Key::Control]).into()],
|
||||
key_groups_mac: None,
|
||||
|
|
@ -200,8 +202,6 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
|
|||
plus: false,
|
||||
slash: false,
|
||||
}]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Confirm")]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, "Cancel")]),
|
||||
]),
|
||||
});
|
||||
|
||||
|
|
@ -268,7 +268,8 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
|
|||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Grabbing });
|
||||
|
||||
responses.add(FrontendMessage::UpdateInputHints {
|
||||
hint_data: HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, "Cancel")])]),
|
||||
// TODO: Fix bug where canceling doesn't work except with the Navigate tool active
|
||||
hint_data: HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])]),
|
||||
});
|
||||
|
||||
self.mouse_position = ipp.mouse.position;
|
||||
|
|
@ -302,6 +303,8 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
|
|||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::ZoomIn });
|
||||
responses.add(FrontendMessage::UpdateInputHints {
|
||||
hint_data: HintData(vec![
|
||||
// TODO: Fix bug where canceling doesn't work except with the Navigate tool active
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo {
|
||||
key_groups: vec![KeysGroup(vec![Key::Control]).into()],
|
||||
key_groups_mac: None,
|
||||
|
|
@ -310,7 +313,6 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
|
|||
plus: false,
|
||||
slash: false,
|
||||
}]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, "Cancel")]),
|
||||
]),
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -274,37 +274,33 @@ impl TransformOperation {
|
|||
use crate::messages::input_mapper::utility_types::input_keyboard::Key;
|
||||
use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo};
|
||||
|
||||
let mut hints = Vec::new();
|
||||
|
||||
let axis_str = |vector: DVec2, separate: bool| match axis_constraint {
|
||||
Axis::Both => {
|
||||
if separate {
|
||||
format!("X: {}, Y: {}", vector.x, vector.y)
|
||||
} else {
|
||||
vector.x.to_string()
|
||||
}
|
||||
}
|
||||
Axis::X => format!("X: {}", vector.x),
|
||||
Axis::Y => format!("Y: {}", vector.y),
|
||||
};
|
||||
|
||||
let value_str = match self {
|
||||
TransformOperation::None => String::new(),
|
||||
TransformOperation::Grabbing(translation) => format!("Translate {}", axis_str(translation.to_dvec(), true)),
|
||||
TransformOperation::Rotating(rotation) => format!("Rotate {}°", rotation.to_f64(snapping) * 360. / std::f64::consts::TAU),
|
||||
TransformOperation::Scaling(scale) => format!("Scale {}", axis_str(scale.to_dvec(snapping), false)),
|
||||
};
|
||||
hints.push(HintInfo::label(value_str));
|
||||
hints.push(HintInfo::keys([Key::Shift], "Precision Mode"));
|
||||
let mut input_hints = Vec::new();
|
||||
input_hints.push(HintInfo::keys([Key::Shift], "Slow Mode"));
|
||||
if matches!(self, TransformOperation::Rotating(_) | TransformOperation::Scaling(_)) {
|
||||
hints.push(HintInfo::keys([Key::Control], "Snap"));
|
||||
input_hints.push(HintInfo::keys([Key::Control], "Snap"));
|
||||
}
|
||||
if matches!(self, TransformOperation::Grabbing(_) | TransformOperation::Scaling(_)) {
|
||||
hints.push(HintInfo::keys([Key::KeyX], "X Axis"));
|
||||
hints.push(HintInfo::keys([Key::KeyY], "Y Axis"));
|
||||
input_hints.push(HintInfo::keys([Key::KeyX], "Along X Axis"));
|
||||
input_hints.push(HintInfo::keys([Key::KeyY], "Along Y Axis"));
|
||||
}
|
||||
|
||||
let hint_data = HintData(vec![HintGroup(hints)]);
|
||||
// TODO: Eventually, move this somewhere else (maybe an overlay in the corner of the viewport, design is TBD) since servicable but not ideal for UI design consistency to have it in the hints bar
|
||||
let axis_text = |vector: DVec2, separate: bool| match (axis_constraint, separate) {
|
||||
(Axis::Both, false) => format!("by {:.3}", vector.x),
|
||||
(Axis::Both, true) => format!("by {:.3}, {:.3}", vector.x, vector.y),
|
||||
(Axis::X, _) => format!("X by {:.3}", vector.x),
|
||||
(Axis::Y, _) => format!("Y by {:.3}", vector.y),
|
||||
};
|
||||
let grs_value_text = match self {
|
||||
TransformOperation::None => String::new(),
|
||||
// TODO: Fix that the translation is showing numbers in viewport space, not document space
|
||||
TransformOperation::Grabbing(translation) => format!("Translating {}", axis_text(translation.to_dvec(), true)),
|
||||
TransformOperation::Rotating(rotation) => format!("Rotating by {:.3}°", rotation.to_f64(snapping) * 360. / std::f64::consts::TAU),
|
||||
TransformOperation::Scaling(scale) => format!("Scaling {}", axis_text(scale.to_dvec(snapping), false)),
|
||||
};
|
||||
let grs_value = vec![HintInfo::label(grs_value_text)];
|
||||
|
||||
let hint_data = HintData(vec![HintGroup(input_hints), HintGroup(grs_value)]);
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -318,15 +318,6 @@ impl ShapeState {
|
|||
document.metadata.document_to_viewport.transform_vector2(offset)
|
||||
}
|
||||
|
||||
pub fn select_anchor_point_by_id(&mut self, layer: LayerNodeIdentifier, id: ManipulatorGroupId, add_to_selection: bool) {
|
||||
if !add_to_selection {
|
||||
self.deselect_all();
|
||||
}
|
||||
let point = ManipulatorPointId::new(id, SelectedType::Anchor);
|
||||
let Some(selected_state) = self.selected_shape_state.get_mut(&layer) else { return };
|
||||
selected_state.select_point(point);
|
||||
}
|
||||
|
||||
/// Select/deselect the first point within the selection threshold.
|
||||
/// Returns a tuple of the points if found and the offset, or `None` otherwise.
|
||||
pub fn change_point_selection(
|
||||
|
|
@ -359,7 +350,7 @@ impl ShapeState {
|
|||
if new_selected {
|
||||
let retain_existing_selection = add_to_selection || already_selected;
|
||||
if !retain_existing_selection {
|
||||
self.deselect_all();
|
||||
self.deselect_all_points();
|
||||
}
|
||||
|
||||
// Add to the selected points
|
||||
|
|
@ -383,20 +374,43 @@ impl ShapeState {
|
|||
None
|
||||
}
|
||||
|
||||
pub fn select_all_points(&mut self, document_network: &NodeNetwork) {
|
||||
for (layer, state) in self.selected_shape_state.iter_mut() {
|
||||
let Some(subpaths) = get_subpaths(*layer, document_network) else { return };
|
||||
for manipulator in get_manipulator_groups(subpaths) {
|
||||
state.select_point(ManipulatorPointId::new(manipulator.id, SelectedType::Anchor));
|
||||
for selected_type in &[SelectedType::InHandle, SelectedType::OutHandle] {
|
||||
state.deselect_point(ManipulatorPointId::new(manipulator.id, *selected_type));
|
||||
pub fn select_anchor_point_by_id(&mut self, layer: LayerNodeIdentifier, id: ManipulatorGroupId, add_to_selection: bool) {
|
||||
if !add_to_selection {
|
||||
self.deselect_all_points();
|
||||
}
|
||||
let point = ManipulatorPointId::new(id, SelectedType::Anchor);
|
||||
let Some(selected_state) = self.selected_shape_state.get_mut(&layer) else { return };
|
||||
selected_state.select_point(point);
|
||||
}
|
||||
|
||||
/// Selects all anchors, and deselects all handles, for the given layer.
|
||||
pub fn select_all_anchors_in_layer(&mut self, document_network: &NodeNetwork, layer: LayerNodeIdentifier) {
|
||||
let Some(state) = self.selected_shape_state.get_mut(&layer) else { return };
|
||||
Self::select_all_anchors_in_layer_with_state(document_network, layer, state);
|
||||
}
|
||||
|
||||
/// Selects all anchors, and deselects all handles, for the selected layers.
|
||||
pub fn select_all_anchors_in_selected_layers(&mut self, document_network: &NodeNetwork) {
|
||||
for (&layer, state) in self.selected_shape_state.iter_mut() {
|
||||
Self::select_all_anchors_in_layer_with_state(document_network, layer, state);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deselect_all(&mut self) {
|
||||
self.selected_shape_state.values_mut().for_each(|state| state.selected_points.clear());
|
||||
/// Internal helper function that selects all anchors, and deselects all handles, for a layer given its [`LayerNodeIdentifier`] and [`SelectedLayerState`].
|
||||
fn select_all_anchors_in_layer_with_state(document_network: &NodeNetwork, layer: LayerNodeIdentifier, state: &mut SelectedLayerState) {
|
||||
let Some(subpaths) = get_subpaths(layer, document_network) else { return };
|
||||
for manipulator in get_manipulator_groups(subpaths) {
|
||||
state.select_point(ManipulatorPointId::new(manipulator.id, SelectedType::Anchor));
|
||||
state.deselect_point(ManipulatorPointId::new(manipulator.id, SelectedType::InHandle));
|
||||
state.deselect_point(ManipulatorPointId::new(manipulator.id, SelectedType::OutHandle));
|
||||
}
|
||||
}
|
||||
|
||||
/// Deselects all points (anchors and handles) across every selected layer.
|
||||
pub fn deselect_all_points(&mut self) {
|
||||
for state in self.selected_shape_state.values_mut() {
|
||||
state.selected_points.clear()
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the shapes we consider for selection, we will choose draggable manipulators from these shapes.
|
||||
|
|
@ -407,6 +421,7 @@ impl ShapeState {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator over the currently selected layers to get their [`LayerNodeIdentifier`]s.
|
||||
pub fn selected_layers(&self) -> impl Iterator<Item = &LayerNodeIdentifier> {
|
||||
self.selected_shape_state.keys()
|
||||
}
|
||||
|
|
@ -427,14 +442,6 @@ impl ShapeState {
|
|||
self.iter(document_network).flat_map(|subpaths| get_manipulator_groups(subpaths))
|
||||
}
|
||||
|
||||
pub fn select_all_anchors(&mut self, document_network: &NodeNetwork, layer: LayerNodeIdentifier) {
|
||||
let Some(subpaths) = get_subpaths(layer, document_network) else { return };
|
||||
let Some(state) = self.selected_shape_state.get_mut(&layer) else { return };
|
||||
for manipulator in get_manipulator_groups(subpaths) {
|
||||
state.select_point(ManipulatorPointId::new(manipulator.id, SelectedType::Anchor))
|
||||
}
|
||||
}
|
||||
|
||||
/// Provide the currently selected points by reference.
|
||||
pub fn selected_points(&self) -> impl Iterator<Item = &'_ ManipulatorPointId> {
|
||||
self.selected_shape_state.values().flat_map(|state| &state.selected_points)
|
||||
|
|
|
|||
|
|
@ -429,10 +429,14 @@ impl Fsm for ArtboardToolFsmState {
|
|||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain to Axis")]),
|
||||
]),
|
||||
ArtboardToolFsmState::Drawing | ArtboardToolFsmState::ResizingBounds => HintData(vec![
|
||||
ArtboardToolFsmState::Drawing => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain Square"), HintInfo::keys([Key::Alt], "From Center")]),
|
||||
]),
|
||||
ArtboardToolFsmState::ResizingBounds => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Shift], "Preserve Aspect Ratio"), HintInfo::keys([Key::Alt], "From Center")]),
|
||||
]),
|
||||
};
|
||||
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
|
|
|
|||
|
|
@ -400,7 +400,7 @@ impl Fsm for BrushToolFsmState {
|
|||
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Draw")]),
|
||||
HintGroup(vec![HintInfo::keys([Key::BracketLeft, Key::BracketRight], "Shrink/Grow Brush")]),
|
||||
]),
|
||||
BrushToolFsmState::Drawing => HintData(vec![]),
|
||||
BrushToolFsmState::Drawing => HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])]),
|
||||
};
|
||||
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
|
|
|
|||
|
|
@ -260,7 +260,10 @@ impl Fsm for EllipseToolFsmState {
|
|||
HintInfo::keys([Key::Shift], "Constrain Circular").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
])]),
|
||||
EllipseToolFsmState::Drawing => HintData(vec![HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain Circular"), HintInfo::keys([Key::Alt], "From Center")])]),
|
||||
EllipseToolFsmState::Drawing => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain Circular"), HintInfo::keys([Key::Alt], "From Center")]),
|
||||
]),
|
||||
};
|
||||
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ impl Fsm for FreehandToolFsmState {
|
|||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
FreehandToolFsmState::Ready => HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Draw Polyline")])]),
|
||||
FreehandToolFsmState::Drawing => HintData(vec![]),
|
||||
FreehandToolFsmState::Drawing => HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])]),
|
||||
};
|
||||
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
|
|
|
|||
|
|
@ -459,7 +459,10 @@ impl Fsm for GradientToolFsmState {
|
|||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Gradient"),
|
||||
HintInfo::keys([Key::Shift], "Snap 15°").prepend_plus(),
|
||||
])]),
|
||||
GradientToolFsmState::Drawing => HintData(vec![HintGroup(vec![HintInfo::keys([Key::Shift], "Snap 15°")])]),
|
||||
GradientToolFsmState::Drawing => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Shift], "Snap 15°")]),
|
||||
]),
|
||||
};
|
||||
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
|
|
|
|||
|
|
@ -234,11 +234,14 @@ impl Fsm for LineToolFsmState {
|
|||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
HintInfo::keys([Key::Control], "Lock Angle").prepend_plus(),
|
||||
])]),
|
||||
LineToolFsmState::Drawing => HintData(vec![HintGroup(vec![
|
||||
LineToolFsmState::Drawing => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![
|
||||
HintInfo::keys([Key::Shift], "Snap 15°"),
|
||||
HintInfo::keys([Key::Alt], "From Center"),
|
||||
HintInfo::keys([Key::Control], "Lock Angle"),
|
||||
])]),
|
||||
]),
|
||||
]),
|
||||
};
|
||||
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
|
|
|
|||
|
|
@ -154,16 +154,22 @@ impl Fsm for NavigateToolFsmState {
|
|||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
NavigateToolFsmState::Ready => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Zoom In"), HintInfo::keys([Key::Shift], "Zoom Out").prepend_plus()]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Zoom"), HintInfo::keys([Key::Control], "Increments").prepend_plus()]),
|
||||
HintGroup(vec![
|
||||
HintInfo::keys_and_mouse([Key::Space], MouseMotion::LmbDrag, ""),
|
||||
HintInfo::mouse(MouseMotion::MmbDrag, "Pan").prepend_slash(),
|
||||
HintInfo::mouse(MouseMotion::MmbDrag, ""),
|
||||
HintInfo::keys_and_mouse([Key::Space], MouseMotion::LmbDrag, "Pan").prepend_slash(),
|
||||
]),
|
||||
HintGroup(vec![HintInfo::keys_and_mouse([Key::Alt], MouseMotion::LmbDrag, "Tilt")]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Zoom"), HintInfo::keys([Key::Control], "Increments").prepend_plus()]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Zoom In"), HintInfo::keys([Key::Shift], "Zoom Out").prepend_plus()]),
|
||||
]),
|
||||
NavigateToolFsmState::Tilting => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Control], "Snap 15°")]),
|
||||
]),
|
||||
NavigateToolFsmState::Zooming => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Control], "Increments")]),
|
||||
]),
|
||||
NavigateToolFsmState::Tilting => HintData(vec![HintGroup(vec![HintInfo::keys([Key::Control], "Snap 15°")])]),
|
||||
NavigateToolFsmState::Zooming => HintData(vec![HintGroup(vec![HintInfo::keys([Key::Control], "Increments")])]),
|
||||
_ => HintData(Vec::new()),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ pub enum PathToolMessage {
|
|||
|
||||
// Tool-specific messages
|
||||
BreakPath,
|
||||
DeselectAllPoints,
|
||||
Delete,
|
||||
DeleteAndBreakPath,
|
||||
DragStop {
|
||||
|
|
@ -58,7 +59,7 @@ pub enum PathToolMessage {
|
|||
shift: Key,
|
||||
},
|
||||
RightClick,
|
||||
SelectAllPoints,
|
||||
SelectAllAnchors,
|
||||
SelectedPointUpdated,
|
||||
SelectedPointXChanged {
|
||||
new_x: f64,
|
||||
|
|
@ -163,7 +164,8 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for PathToo
|
|||
Delete,
|
||||
NudgeSelectedPoints,
|
||||
Enter,
|
||||
SelectAllPoints,
|
||||
SelectAllAnchors,
|
||||
DeselectAllPoints,
|
||||
BreakPath,
|
||||
DeleteAndBreakPath,
|
||||
),
|
||||
|
|
@ -174,7 +176,6 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for PathToo
|
|||
DragStop,
|
||||
PointerMove,
|
||||
Delete,
|
||||
SelectAllPoints,
|
||||
BreakPath,
|
||||
DeleteAndBreakPath,
|
||||
),
|
||||
|
|
@ -184,9 +185,10 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for PathToo
|
|||
PointerMove,
|
||||
Delete,
|
||||
Enter,
|
||||
SelectAllPoints,
|
||||
BreakPath,
|
||||
DeleteAndBreakPath,
|
||||
Escape,
|
||||
RightClick,
|
||||
),
|
||||
InsertPoint => actions!(PathToolMessageDiscriminant;
|
||||
Enter,
|
||||
|
|
@ -324,11 +326,12 @@ impl PathToolData {
|
|||
}
|
||||
self.drag_start_pos = input.mouse.position;
|
||||
self.previous_mouse_position = input.mouse.position;
|
||||
shape_editor.select_all_anchors(&document.network, layer);
|
||||
shape_editor.select_all_anchors_in_layer(&document.network, layer);
|
||||
|
||||
PathToolFsmState::Dragging
|
||||
} else {
|
||||
}
|
||||
// Start drawing a box
|
||||
else {
|
||||
self.drag_start_pos = input.mouse.position;
|
||||
self.previous_mouse_position = input.mouse.position;
|
||||
|
||||
|
|
@ -495,7 +498,12 @@ impl Fsm for PathToolFsmState {
|
|||
}
|
||||
(PathToolFsmState::Dragging, PathToolMessage::Escape | PathToolMessage::RightClick) => {
|
||||
responses.add(DocumentMessage::AbortTransaction);
|
||||
shape_editor.deselect_all();
|
||||
shape_editor.deselect_all_points();
|
||||
tool_data.snap_manager.cleanup(responses);
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
(PathToolFsmState::DrawingBox, PathToolMessage::Escape | PathToolMessage::RightClick) => {
|
||||
responses.add(DocumentMessage::AbortTransaction);
|
||||
tool_data.snap_manager.cleanup(responses);
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
|
|
@ -525,7 +533,7 @@ impl Fsm for PathToolFsmState {
|
|||
if tool_data.drag_start_pos.distance(input.mouse.position) <= DRAG_THRESHOLD && !shift_pressed {
|
||||
let clicked_selected = shape_editor.selected_points().any(|&point| nearest_point == Some(point));
|
||||
if clicked_selected {
|
||||
shape_editor.deselect_all();
|
||||
shape_editor.deselect_all_points();
|
||||
shape_editor.change_point_selection(&document.network, &document.metadata, input.mouse.position, SELECTION_THRESHOLD, false);
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
}
|
||||
|
|
@ -570,8 +578,13 @@ impl Fsm for PathToolFsmState {
|
|||
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
(_, PathToolMessage::SelectAllPoints) => {
|
||||
shape_editor.select_all_points(&document.network);
|
||||
(_, PathToolMessage::SelectAllAnchors) => {
|
||||
shape_editor.select_all_anchors_in_selected_layers(&document.network);
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
(_, PathToolMessage::DeselectAllPoints) => {
|
||||
shape_editor.deselect_all_points();
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
|
|
@ -609,26 +622,45 @@ impl Fsm for PathToolFsmState {
|
|||
}
|
||||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
let general_hint_data = HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Select Point"), HintInfo::keys([Key::Shift], "Extend Selection").prepend_plus()]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Drag Selected")]),
|
||||
HintGroup(vec![HintInfo::arrow_keys("Nudge Selected"), HintInfo::keys([Key::Shift], "10x").prepend_plus()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::KeyG, Key::KeyR, Key::KeyS], "Grab/Rotate/Scale Selected")]),
|
||||
]);
|
||||
|
||||
let hint_data = match self {
|
||||
PathToolFsmState::Ready => general_hint_data,
|
||||
PathToolFsmState::Dragging => HintData(vec![HintGroup(vec![
|
||||
HintInfo::keys([Key::Alt], "Split/Align Handles (Toggle)"),
|
||||
HintInfo::keys([Key::Shift], "Share Lengths of Aligned Handles"),
|
||||
])]),
|
||||
PathToolFsmState::DrawingBox => HintData(vec![HintGroup(vec![
|
||||
PathToolFsmState::Ready => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Select Point"), HintInfo::keys([Key::Shift], "Extend Selection").prepend_plus()]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Insert Point on Segment")]),
|
||||
// TODO: Only show the following hints if at least one point is selected
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Drag Selected")]),
|
||||
HintGroup(vec![HintInfo::keys([Key::KeyG, Key::KeyR, Key::KeyS], "Grab/Rotate/Scale Selected")]),
|
||||
HintGroup(vec![HintInfo::arrow_keys("Nudge Selected"), HintInfo::keys([Key::Shift], "10x").prepend_plus()]),
|
||||
HintGroup(vec![
|
||||
HintInfo::keys([Key::Delete], "Delete Selected"),
|
||||
// TODO: Only show the following hints if at least one anchor is selected
|
||||
HintInfo::keys([Key::Accel], "No Dissolve").prepend_plus(),
|
||||
HintInfo::keys([Key::Shift], "Break Anchor").prepend_plus(),
|
||||
]),
|
||||
]),
|
||||
PathToolFsmState::Dragging => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![
|
||||
// TODO: Make hint dynamically say "Make Handle Smooth" or "Make Handle Sharp" based on its current state
|
||||
// TODO: Switch this to the "S" key
|
||||
// TODO: Only show this if a handle (not an anchor) is being dragged, and disable that shortcut so it can't be pressed even with the hint not shown
|
||||
HintInfo::keys([Key::Alt], "Toggle Smooth/Sharp Handles"),
|
||||
// TODO: Switch this to the "Alt" key (since it's equivalent to the "From Center" modifier when drawing a line)
|
||||
// TODO: Show this only when a handle is being dragged
|
||||
HintInfo::keys([Key::Shift], "Equidistant Handles (Smooth Only)"),
|
||||
// TODO: Add "Snap 15°" modifier with the "Shift" key (only when a handle is being dragged)
|
||||
// TODO: Add "Lock Angle" modifier with the "Ctrl" key (only when a handle is being dragged)
|
||||
]),
|
||||
]),
|
||||
PathToolFsmState::DrawingBox => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Select Area"),
|
||||
HintInfo::keys([Key::Shift], "Extend Selection").prepend_plus(),
|
||||
])]),
|
||||
]),
|
||||
]),
|
||||
PathToolFsmState::InsertPoint => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Insert Point")]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel Insertion").prepend_slash()]),
|
||||
]),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -721,11 +721,23 @@ impl Fsm for PenToolFsmState {
|
|||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
PenToolFsmState::Ready => HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Draw Path")])]),
|
||||
PenToolFsmState::DraggingHandle | PenToolFsmState::PlacingAnchor => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Add Anchor"), HintInfo::mouse(MouseMotion::LmbDrag, "Add Handle")]),
|
||||
PenToolFsmState::PlacingAnchor => HintData(vec![
|
||||
HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::Rmb, ""),
|
||||
HintInfo::keys([Key::Escape], "").prepend_slash(),
|
||||
HintInfo::keys([Key::Enter], "End Path").prepend_slash(),
|
||||
]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Shift], "Snap 15°"), HintInfo::keys([Key::Control], "Lock Angle")]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Alt], "Break Handle")]), // TODO: Show this only when dragging a handle
|
||||
HintGroup(vec![HintInfo::keys([Key::Enter], "End Path")]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Add Sharp Point"), HintInfo::mouse(MouseMotion::LmbDrag, "Add Smooth Point")]),
|
||||
]),
|
||||
PenToolFsmState::DraggingHandle => HintData(vec![
|
||||
HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::Rmb, ""),
|
||||
HintInfo::keys([Key::Escape], "").prepend_slash(),
|
||||
HintInfo::keys([Key::Enter], "End Path").prepend_slash(),
|
||||
]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Shift], "Snap 15°"), HintInfo::keys([Key::Control], "Lock Angle")]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Alt], "Bend Handle")]),
|
||||
]),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ pub struct PolygonOptions {
|
|||
fill: ToolColorOptions,
|
||||
stroke: ToolColorOptions,
|
||||
vertices: u32,
|
||||
primitive_shape_type: PrimitiveShapeType,
|
||||
polygon_type: PolygonType,
|
||||
}
|
||||
|
||||
impl Default for PolygonOptions {
|
||||
|
|
@ -32,7 +32,7 @@ impl Default for PolygonOptions {
|
|||
line_weight: 5.,
|
||||
fill: ToolColorOptions::new_secondary(),
|
||||
stroke: ToolColorOptions::new_primary(),
|
||||
primitive_shape_type: PrimitiveShapeType::Polygon,
|
||||
polygon_type: PolygonType::Convex,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -53,8 +53,8 @@ pub enum PolygonToolMessage {
|
|||
}
|
||||
|
||||
#[derive(PartialEq, Copy, Clone, Debug, Serialize, Deserialize, specta::Type)]
|
||||
pub enum PrimitiveShapeType {
|
||||
Polygon = 0,
|
||||
pub enum PolygonType {
|
||||
Convex = 0,
|
||||
Star = 1,
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ pub enum PolygonOptionsUpdate {
|
|||
FillColor(Option<Color>),
|
||||
FillColorType(ToolColorType),
|
||||
LineWeight(f64),
|
||||
PrimitiveShapeType(PrimitiveShapeType),
|
||||
PolygonType(PolygonType),
|
||||
StrokeColor(Option<Color>),
|
||||
StrokeColorType(ToolColorType),
|
||||
Vertices(u32),
|
||||
|
|
@ -93,16 +93,16 @@ fn create_sides_widget(vertices: u32) -> WidgetHolder {
|
|||
.widget_holder()
|
||||
}
|
||||
|
||||
fn create_star_option_widget(primitive_shape_type: PrimitiveShapeType) -> WidgetHolder {
|
||||
fn create_star_option_widget(polygon_type: PolygonType) -> WidgetHolder {
|
||||
let entries = vec![
|
||||
RadioEntryData::new("polygon")
|
||||
.label("Polygon")
|
||||
.on_update(move |_| PolygonToolMessage::UpdateOptions(PolygonOptionsUpdate::PrimitiveShapeType(PrimitiveShapeType::Polygon)).into()),
|
||||
RadioEntryData::new("convex")
|
||||
.label("Convex")
|
||||
.on_update(move |_| PolygonToolMessage::UpdateOptions(PolygonOptionsUpdate::PolygonType(PolygonType::Convex)).into()),
|
||||
RadioEntryData::new("star")
|
||||
.label("Star")
|
||||
.on_update(move |_| PolygonToolMessage::UpdateOptions(PolygonOptionsUpdate::PrimitiveShapeType(PrimitiveShapeType::Star)).into()),
|
||||
.on_update(move |_| PolygonToolMessage::UpdateOptions(PolygonOptionsUpdate::PolygonType(PolygonType::Star)).into()),
|
||||
];
|
||||
RadioInput::new(entries).selected_index(Some(primitive_shape_type as u32)).widget_holder()
|
||||
RadioInput::new(entries).selected_index(Some(polygon_type as u32)).widget_holder()
|
||||
}
|
||||
|
||||
fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
||||
|
|
@ -118,7 +118,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
|||
impl LayoutHolder for PolygonTool {
|
||||
fn layout(&self) -> Layout {
|
||||
let mut widgets = vec![
|
||||
create_star_option_widget(self.options.primitive_shape_type),
|
||||
create_star_option_widget(self.options.polygon_type),
|
||||
Separator::new(SeparatorType::Related).widget_holder(),
|
||||
create_sides_widget(self.options.vertices),
|
||||
];
|
||||
|
|
@ -156,7 +156,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for Polygon
|
|||
};
|
||||
match action {
|
||||
PolygonOptionsUpdate::Vertices(vertices) => self.options.vertices = vertices,
|
||||
PolygonOptionsUpdate::PrimitiveShapeType(primitive_shape_type) => self.options.primitive_shape_type = primitive_shape_type,
|
||||
PolygonOptionsUpdate::PolygonType(polygon_type) => self.options.polygon_type = polygon_type,
|
||||
PolygonOptionsUpdate::FillColor(color) => {
|
||||
self.options.fill.custom_color = color;
|
||||
self.options.fill.color_type = ToolColorType::Custom;
|
||||
|
|
@ -242,9 +242,9 @@ impl Fsm for PolygonToolFsmState {
|
|||
polygon_data.start(document, input);
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
|
||||
let subpath = match tool_options.primitive_shape_type {
|
||||
PrimitiveShapeType::Polygon => bezier_rs::Subpath::new_regular_polygon(DVec2::ZERO, tool_options.vertices as u64, 1.),
|
||||
PrimitiveShapeType::Star => bezier_rs::Subpath::new_star_polygon(DVec2::ZERO, tool_options.vertices as u64, 1., 0.5),
|
||||
let subpath = match tool_options.polygon_type {
|
||||
PolygonType::Convex => bezier_rs::Subpath::new_regular_polygon(DVec2::ZERO, tool_options.vertices as u64, 1.),
|
||||
PolygonType::Star => bezier_rs::Subpath::new_star_polygon(DVec2::ZERO, tool_options.vertices as u64, 1., 0.5),
|
||||
};
|
||||
let layer = graph_modification_utils::new_vector_layer(vec![subpath], NodeId(generate_uuid()), document.new_layer_parent(), responses);
|
||||
polygon_data.layer = Some(layer);
|
||||
|
|
@ -302,10 +302,13 @@ impl Fsm for PolygonToolFsmState {
|
|||
let hint_data = match self {
|
||||
PolygonToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Polygon"),
|
||||
HintInfo::keys([Key::Shift], "Constrain 1:1 Aspect").prepend_plus(),
|
||||
HintInfo::keys([Key::Shift], "Constrain Regular").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
])]),
|
||||
PolygonToolFsmState::Drawing => HintData(vec![HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain 1:1 Aspect"), HintInfo::keys([Key::Alt], "From Center")])]),
|
||||
PolygonToolFsmState::Drawing => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain Regular"), HintInfo::keys([Key::Alt], "From Center")]),
|
||||
]),
|
||||
};
|
||||
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
|
|
|
|||
|
|
@ -267,7 +267,10 @@ impl Fsm for RectangleToolFsmState {
|
|||
HintInfo::keys([Key::Shift], "Constrain Square").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
])]),
|
||||
RectangleToolFsmState::Drawing => HintData(vec![HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain Square"), HintInfo::keys([Key::Alt], "From Center")])]),
|
||||
RectangleToolFsmState::Drawing => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain Square"), HintInfo::keys([Key::Alt], "From Center")]),
|
||||
]),
|
||||
};
|
||||
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
|
|
|
|||
|
|
@ -1025,7 +1025,6 @@ impl Fsm for SelectToolFsmState {
|
|||
SelectToolFsmState::Ready { selection } => {
|
||||
let hint_data = HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Drag Selected")]),
|
||||
HintGroup(vec![HintInfo::keys([Key::KeyG, Key::KeyR, Key::KeyS], "Grab/Rotate/Scale Selected")]),
|
||||
HintGroup({
|
||||
let mut hints = vec![HintInfo::mouse(MouseMotion::Lmb, "Select Object"), HintInfo::keys([Key::Shift], "Extend Selection").prepend_plus()];
|
||||
if *selection == NestedSelectionBehavior::Shallowest {
|
||||
|
|
@ -1037,6 +1036,7 @@ impl Fsm for SelectToolFsmState {
|
|||
HintInfo::mouse(MouseMotion::LmbDrag, "Select Area"),
|
||||
HintInfo::keys([Key::Shift], "Extend Selection").prepend_plus(),
|
||||
]),
|
||||
HintGroup(vec![HintInfo::keys([Key::KeyG, Key::KeyR, Key::KeyS], "Grab/Rotate/Scale Selected")]),
|
||||
HintGroup(vec![
|
||||
HintInfo::arrow_keys("Nudge Selected"),
|
||||
HintInfo::keys([Key::Shift], "10x").prepend_plus(),
|
||||
|
|
@ -1053,14 +1053,17 @@ impl Fsm for SelectToolFsmState {
|
|||
SelectToolFsmState::Dragging => {
|
||||
let hint_data = HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain to Axis")]),
|
||||
HintGroup(vec![
|
||||
HintInfo::keys_and_mouse([Key::Alt], MouseMotion::LmbDrag, "Move Duplicate"),
|
||||
HintInfo::keys([Key::Alt], "Move Duplicate"),
|
||||
HintInfo::keys([Key::Control, Key::KeyD], "Place Duplicate").add_mac_keys([Key::Command, Key::KeyD]),
|
||||
]),
|
||||
]);
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
SelectToolFsmState::DrawingBox { .. } => {
|
||||
// TODO: Add hint and implement functionality for holding Shift to extend the selection, thus preventing the prior selection from being cleared
|
||||
// TODO: Also fix the current functionality so canceling the box select doesn't clear the prior selection
|
||||
let hint_data = HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])]);
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -297,6 +297,7 @@ impl Fsm for SplineToolFsmState {
|
|||
let hint_data = match self {
|
||||
SplineToolFsmState::Ready => HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Draw Spline")])]),
|
||||
SplineToolFsmState::Drawing => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Extend Spline")]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Enter], "End Spline")]),
|
||||
]),
|
||||
|
|
|
|||
|
|
@ -455,11 +455,14 @@ impl Fsm for TextToolFsmState {
|
|||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
TextToolFsmState::Ready => HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Add Text"), HintInfo::mouse(MouseMotion::Lmb, "Edit Text")])]),
|
||||
TextToolFsmState::Editing => HintData(vec![HintGroup(vec![
|
||||
HintInfo::keys([Key::Control, Key::Enter], "Commit Edit").add_mac_keys([Key::Command, Key::Enter]),
|
||||
HintInfo::keys([Key::Escape], "Discard Edit"),
|
||||
])]),
|
||||
TextToolFsmState::Ready => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Place Text")]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Edit Text")]),
|
||||
]),
|
||||
TextToolFsmState::Editing => HintData(vec![
|
||||
HintGroup(vec![HintInfo::keys([Key::Escape], "Discard Changes")]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Control, Key::Enter], "Commit Changes").add_mac_keys([Key::Command, Key::Enter])]),
|
||||
]),
|
||||
};
|
||||
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
|
|
|
|||
Loading…
Reference in New Issue