Skip to content

Commit

Permalink
fix: select multiple lines at once and at station to multiple at once
Browse files Browse the repository at this point in the history
  • Loading branch information
CalliEve committed Dec 19, 2024
1 parent aca2ed3 commit 85c6036
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 86 deletions.
5 changes: 3 additions & 2 deletions src/algorithm/drawing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ where
map.draw(&context, state.get_canvas_state(), 1.0);

state
.get_selected_line()
.inspect(|d| d.draw(map, &context, state.get_canvas_state()));
.get_selected_lines()
.iter()
.for_each(|d| d.draw(map, &context, state.get_canvas_state()));

state
.get_box_select()
Expand Down
52 changes: 23 additions & 29 deletions src/components/canvas/mouse_down.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,24 @@ pub fn on_mouse_down(map_state: &mut MapState, ev: &UiEvent, shift_key: bool) {
}

// Handle a click while having a new line selected
if let Some(selected_line) = map_state
.get_selected_line()
.copied()
{
if let Some(station_at_pos) = station_at_node {
let (before, after) = selected_line.get_before_after();
let mut line = map
.get_or_add_line(selected_line.get_line())
.clone();

line.add_station(&mut map, station_at_pos, before, after);

map.add_line(line);
map_state.set_map(map);
map_state.clear_selected_line();
let selected_lines = map_state
.get_selected_lines()
.to_vec();
if !selected_lines.is_empty() {
for selected_line in selected_lines {
if let Some(station_at_pos) = station_at_node {
let (before, after) = selected_line.get_before_after();
let mut line = map
.get_or_add_line(selected_line.get_line())
.clone();

line.add_station(&mut map, station_at_pos, before, after);

map.add_line(line);
}
}
map_state.set_map(map);
map_state.clear_selected_lines();
return;
}

Expand Down Expand Up @@ -149,21 +151,13 @@ pub fn on_mouse_down(map_state: &mut MapState, ev: &UiEvent, shift_key: bool) {
}

// Handle a click on a line
if let Some(selected_line) = map
.line_at_node(mouse_pos)
.cloned()
let selected_lines = map
.lines_at_node(mouse_pos)
.into_iter()
.map(|l| SelectedLine::new(&l, &map, mouse_pos, Some(mouse_pos)))
{
map_state.set_selected_line(selected_line);
for edge in map.get_edges() {
if edge
.get_nodes()
.contains(&mouse_pos)
{
edge.print_info();
break;
}
}
.collect::<Vec<_>>();
if !selected_lines.is_empty() {
map_state.set_selected_lines(selected_lines);
}

// Select the clicked edge, unless this was a double click.
Expand Down
13 changes: 9 additions & 4 deletions src/components/canvas/mouse_move.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,16 @@ pub fn on_mouse_move(map_state_signal: &RwSignal<MapState>, ev: &UiEvent) {
let mouse_pos = GridNode::from_canvas_pos(canvas_pos, canvas_state);

// Handle move of selected line.
if let Some(selected) = map_state.get_mut_selected_line() {
if selected.get_current_hover() != mouse_pos {
selected.set_current_hover(mouse_pos);
map_state_signal.set(map_state);
if !map_state
.get_selected_lines()
.is_empty()
{
for selected in map_state.get_mut_selected_lines() {
if selected.get_current_hover() != mouse_pos {
selected.set_current_hover(mouse_pos);
}
}
map_state_signal.set(map_state);
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/canvas/mouse_out.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::MapState;
///
/// [mouseout]: https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseout_event
pub fn on_mouse_out(map_state: &mut MapState) {
map_state.clear_selected_line();
map_state.clear_selected_lines();
map_state.clear_box_select();
map_state.clear_drag_offset();
}
63 changes: 37 additions & 26 deletions src/components/canvas/mouse_up.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::{
},
models::{
GridNode,
SelectedLine,
SelectedStation,
},
MapState,
Expand Down Expand Up @@ -62,7 +63,10 @@ pub fn on_mouse_up(
}
},
ActionType::RemoveLine => {
if let Some(selected_line) = map.line_at_node(mouse_pos) {
for selected_line in map
.lines_at_node(mouse_pos)
.clone()
{
if let Err(err) = map.remove_line(selected_line.get_id()) {
error_state.update(|state| state.set_error(err));
}
Expand Down Expand Up @@ -99,37 +103,47 @@ pub fn on_mouse_up(
}

// Handle a mouseup while having a line selected
if let Some(selected_line) = map_state
.get_selected_line()
.copied()
{
if let Some(station_at_pos) = station_at_node {
let (before, after) = selected_line.get_before_after();
let mut line = map
.get_or_add_line(selected_line.get_line())
.clone();

line.add_station(&mut map, station_at_pos, before, after);
let selected_lines = map_state
.get_selected_lines()
.to_vec();
if !selected_lines.is_empty() {
let mut added_station = false;
for selected_line in selected_lines.clone() {
if let Some(station_at_pos) = station_at_node {
let (before, after) = selected_line.get_before_after();
let mut line = map
.get_or_add_line(selected_line.get_line())
.clone();

line.add_station(&mut map, station_at_pos, before, after);

if let Some(before_station) = before {
let edge_id = map.get_edge_id_between(before_station, station_at_pos);
recalculate_edge_nodes(&mut map, edge_id);
}

if let Some(before_station) = before {
let edge_id = map.get_edge_id_between(before_station, station_at_pos);
recalculate_edge_nodes(&mut map, edge_id);
}
if let Some(after_station) = after {
let edge_id = map.get_edge_id_between(station_at_pos, after_station);
recalculate_edge_nodes(&mut map, edge_id);
}

if let Some(after_station) = after {
let edge_id = map.get_edge_id_between(station_at_pos, after_station);
recalculate_edge_nodes(&mut map, edge_id);
map.add_line(line);
added_station = true;
}
}

map.add_line(line);
if added_station {
map_state.set_map(map);
map_state.clear_all_selections();
map_state.clear_selected_lines();
return;
}

map_state.clear_selected_line();
map_state.clear_selected_lines();

if let Some(grabbed_at) = selected_line.get_grabbed_at() {
if let Some(grabbed_at) = selected_lines
.first()
.and_then(SelectedLine::get_grabbed_at)
{
if grabbed_at == mouse_pos {
// Handle a single click on an edge
if edge_at_node.is_some()
Expand All @@ -154,9 +168,6 @@ pub fn on_mouse_up(
map_state.set_clicked_on_edge(selected_edge, canvas_pos);
return;
}
} else {
map_state.clear_all_selections();
return;
}
}
}
Expand Down
11 changes: 7 additions & 4 deletions src/components/molecules/error_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use wasm_bindgen::{
JsCast,
};

use crate::components::ErrorState;
use crate::{
components::ErrorState,
Error,
};

/// A pop-up box for displaying errors.
#[component]
Expand All @@ -15,7 +18,7 @@ pub fn ErrorBox() -> impl IntoView {
use_context::<RwSignal<ErrorState>>().expect("to have found the global error state");

let on_click = move |_| {
error_state.update(|state| state.clear_error());
error_state.update(ErrorState::clear_error);
};

let has_error = move || {
Expand All @@ -27,11 +30,11 @@ pub fn ErrorBox() -> impl IntoView {
let err = error_state
.get()
.get_error()
.map(|e| e.to_user_friendly_string());
.map(Error::to_user_friendly_string);

if err.is_some() {
let f = Closure::wrap(Box::new(move || {
error_state.update(|state| state.clear_error());
error_state.update(ErrorState::clear_error);
}) as Box<dyn Fn()>);
window()
.set_timeout_with_callback_and_timeout_and_arguments_0(
Expand Down
2 changes: 1 addition & 1 deletion src/components/organisms/canvas_controls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ pub fn CanvasControls() -> impl IntoView {
{
state.set_map(map);
}
})
});
}
if let Some(error) = resp.error {
error_state.update(|state| {
Expand Down
2 changes: 1 addition & 1 deletion src/components/organisms/sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub fn Sidebar() -> impl IntoView {
map_state.update(|state| {
state.clear_all_selections();
let line = SelectedLine::new_line(state.get_mut_map());
state.set_selected_line(line);
state.set_selected_lines(vec![line]);
});
};

Expand Down
3 changes: 3 additions & 0 deletions src/components/state/error.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
//! Contains the [`ErrorState`] and its methods.
use crate::Error;

/// Contains the current error state.
/// This state is then used to display the error message to the user.
#[derive(Clone, Debug)]
pub struct ErrorState {
/// The error last encountered.
error: Option<Error>,
}

Expand Down
33 changes: 17 additions & 16 deletions src/components/state/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ pub struct MapState {
map: Map,
/// The currently selected [`crate::models::Station`]s.
selected_stations: Vec<SelectedStation>,
/// The currently selected [`crate::models::Line`].
selected_line: Option<SelectedLine>,
/// The currently selected [`crate::models::Line`]s.
selected_lines: Vec<SelectedLine>,
/// The type of action that is currently selected.
selected_action: Option<ActionType>,
/// The currently selected edges.
Expand Down Expand Up @@ -89,7 +89,7 @@ impl MapState {
Self {
map,
selected_stations: Vec::new(),
selected_line: None,
selected_lines: Vec::new(),
selected_action: None,
selected_edges: Vec::new(),
canvas: CanvasState::default(),
Expand All @@ -106,7 +106,7 @@ impl MapState {
/// Clear all selections.
pub fn clear_all_selections(&mut self) {
self.clear_selected_stations();
self.clear_selected_line();
self.clear_selected_lines();
self.clear_selected_action();
self.clear_selected_edges();
self.clear_box_select();
Expand Down Expand Up @@ -192,26 +192,27 @@ impl MapState {
self.selected_action = None;
}

/// A mutable getter method for the selected line.
pub fn get_mut_selected_line(&mut self) -> Option<&mut SelectedLine> {
self.selected_line
/// A mutable getter method for the selected lines.
pub fn get_mut_selected_lines(&mut self) -> &mut [SelectedLine] {
self.selected_lines
.as_mut()
}

/// A getter method for the selected line.
pub fn get_selected_line(&self) -> Option<&SelectedLine> {
self.selected_line
/// A getter method for the selected lines.
pub fn get_selected_lines(&self) -> &[SelectedLine] {
self.selected_lines
.as_ref()
}

/// A setter method for the selected line.
pub fn set_selected_line(&mut self, line: SelectedLine) {
self.selected_line = Some(line);
/// A setter method for the selected lines.
pub fn set_selected_lines(&mut self, lines: Vec<SelectedLine>) {
self.selected_lines = lines;
}

/// Set the selected line to None.
pub fn clear_selected_line(&mut self) {
self.selected_line = None;
/// Clear the list of selected lines.
pub fn clear_selected_lines(&mut self) {
self.selected_lines
.clear();
}

/// A getter method for the selected edges.
Expand Down
6 changes: 4 additions & 2 deletions src/models/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,12 @@ impl Map {
}

/// Get the line that goes through the given grid node.
pub fn line_at_node(&self, node: GridNode) -> Option<&Line> {
pub fn lines_at_node(&self, node: GridNode) -> Vec<Line> {
self.lines
.values()
.find(|l| l.visits_node(self, node))
.filter(|l| l.visits_node(self, node))
.cloned()
.collect::<Vec<_>>()
}

/// Get the edge located on the given grid node.
Expand Down

0 comments on commit 85c6036

Please sign in to comment.