Add Snapping Options to the Snap Dropdown Menu (#1321)

* [wip]feat: add snapping options

* [wip]fix: use svelte component for optionsWidget

* fix: use apt PopoverButton types

* refactor: minor formatting improvements

* Fix popover layout

* [wip]feat: attempt implementing CheckboxInputData struct

* fix: use correct Checkbox struct 's default method

* fix: revert adding CheckboxInputData struct

- This reverts commit 2a481887fc.

* feat: use checkboxes for snapping options

* feat: add label to dropdown checkbox elements

* fix: separate Snap dropdown menu elements
- move each element into separate row

* [wip]feat: modularize snapping states
- maintain individual snapping states for document

* fix: snapping checkboxes' behavior
- checkboxes now update internal snapping state

* refactor: update snap states individually
- this prevents out-of-sync states
- enables reusing existing snap state object

* feat: snap to boxes and nodes conditionally

* [wip]feat: attempt to invert checkbox on update
- attempt implementing mutable WidgetCallback struct
- attempt using above struct to invert checkbox state on update

* Fix widget diffing

* refactor: remove unused code

* feat: align checkboxes consistently with labels

* feat: use separators to stylize snapping menu
- removes need for custom CSS and label property
- ensures consistency across the application

* refactor: remove unneeded css

---------

Co-authored-by: hypercube <0hypercube@gmail.com>, TrueDoctor <dennis@kobert.dev>
This commit is contained in:
Dhruv
2023-07-15 15:07:18 +05:30
committed by Keavon Chambers
co-authored by hypercube <0hypercube@gmail.com>, TrueDoctor
parent 4c9daadb01
commit 743803ce04
12 changed files with 204 additions and 41 deletions
@@ -216,7 +216,9 @@ impl SnapManager {
snap_x: bool,
snap_y: bool,
) {
if document_message_handler.snapping_enabled {
let snapping_enabled = document_message_handler.snapping_state.snapping_enabled;
let bounding_box_snapping = document_message_handler.snapping_state.bounding_box_snapping;
if snapping_enabled && bounding_box_snapping {
self.snap_x = snap_x;
self.snap_y = snap_y;
@@ -235,7 +237,9 @@ impl SnapManager {
///
/// This should be called after start_snap
pub fn add_snap_points(&mut self, document_message_handler: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, snap_points: impl Iterator<Item = DVec2>) {
if document_message_handler.snapping_enabled {
let snapping_enabled = document_message_handler.snapping_state.snapping_enabled;
let node_snapping = document_message_handler.snapping_state.node_snapping;
if snapping_enabled && node_snapping {
let snap_points = snap_points.filter(|&pos| pos.x >= 0. && pos.y >= 0. && pos.x < input.viewport_bounds.size().x && pos.y <= input.viewport_bounds.size().y);
if let Some(targets) = &mut self.point_targets {
targets.extend(snap_points);
@@ -259,6 +263,10 @@ impl SnapManager {
) {
let Some(vector_data) = &layer.as_vector_data() else { return };
if !document_message_handler.snapping_state.node_snapping {
return;
};
let transform = document_message_handler.document_legacy.multiply_transforms(path).unwrap();
let snap_points = vector_data
.manipulator_groups()
@@ -299,7 +307,7 @@ impl SnapManager {
/// Finds the closest snap from an array of layers to the specified snap targets in viewport coords.
/// Returns 0 for each axis that there is no snap less than the snap tolerance.
pub fn snap_layers(&mut self, responses: &mut VecDeque<Message>, document_message_handler: &DocumentMessageHandler, snap_anchors: Vec<DVec2>, mouse_delta: DVec2) -> DVec2 {
if document_message_handler.snapping_enabled {
if document_message_handler.snapping_state.snapping_enabled {
self.calculate_snap(snap_anchors.iter().map(move |&snap| mouse_delta + snap), responses)
} else {
DVec2::ZERO
@@ -308,7 +316,7 @@ impl SnapManager {
/// Handles snapping of a viewport position, returning another viewport position.
pub fn snap_position(&mut self, responses: &mut VecDeque<Message>, document_message_handler: &DocumentMessageHandler, position_viewport: DVec2) -> DVec2 {
if document_message_handler.snapping_enabled {
if document_message_handler.snapping_state.snapping_enabled {
self.calculate_snap([position_viewport].into_iter(), responses) + position_viewport
} else {
position_viewport