Skip to content

Commit dbc1991

Browse files
authored
Set the mouse cursor in the canvas based on the current tool and its state (#480)
* Add FrontendMouseCursor and DisplayMouseCursor * Add update_cursor method to the Fsm trait and implement it for all tools * Rename DisplayMouseCursor to UpdateMouseCursor * Add 'To CSS Cursor Property' transform decorator and change the mouse cursor in the canvas based on the current tool and its state * Implement update_cursor for Navigate tool properly * Keep the cursor when dragging outside of the canvas * Change the mouse cursor to 'zoom-in' when LMB dragging on canvas with Navigate tool * Rename FrontendMouseCursor to MouseCursorIcon * Rename 'event' to 'e' and replace v-on with @ * Change the definition of the MouseCursorIcon type in TS * Replace switch with dictionary look-up * Move the definition of MouseCursorIcon closer to where it's used
1 parent 9b36e6a commit dbc1991

File tree

17 files changed

+163
-4
lines changed

17 files changed

+163
-4
lines changed

editor/src/frontend/frontend_message.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::utility_types::FrontendDocumentDetails;
1+
use super::utility_types::{FrontendDocumentDetails, MouseCursorIcon};
22
use crate::document::layer_panel::{LayerPanelEntry, RawBuffer};
33
use crate::message_prelude::*;
44
use crate::misc::HintData;
@@ -37,6 +37,7 @@ pub enum FrontendMessage {
3737
UpdateDocumentRulers { origin: (f64, f64), spacing: f64, interval: f64 },
3838
UpdateDocumentScrollbars { position: (f64, f64), size: (f64, f64), multiplier: (f64, f64) },
3939
UpdateInputHints { hint_data: HintData },
40+
UpdateMouseCursor { cursor: MouseCursorIcon },
4041
UpdateOpenDocumentsList { open_documents: Vec<FrontendDocumentDetails> },
4142
UpdateWorkingColors { primary: Color, secondary: Color },
4243
}

editor/src/frontend/utility_types.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,12 @@ pub struct FrontendDocumentDetails {
66
pub name: String,
77
pub id: u64,
88
}
9+
10+
#[derive(Clone, Copy, Debug, Eq, Deserialize, PartialEq, Serialize)]
11+
pub enum MouseCursorIcon {
12+
Default,
13+
ZoomIn,
14+
ZoomOut,
15+
Grabbing,
16+
Crosshair,
17+
}

editor/src/viewport_tools/tool.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub trait Fsm {
2727
) -> Self;
2828

2929
fn update_hints(&self, responses: &mut VecDeque<Message>);
30+
fn update_cursor(&self, responses: &mut VecDeque<Message>);
3031
}
3132

3233
#[derive(Debug, Clone)]

editor/src/viewport_tools/tool_message.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,6 @@ pub enum ToolMessage {
4949
#[child]
5050
Shape(ShapeMessage),
5151
SwapColors,
52+
UpdateCursor,
5253
UpdateHints,
5354
}

editor/src/viewport_tools/tool_message_handler.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,13 @@ impl MessageHandler<ToolMessage, (&DocumentMessageHandler, &InputPreprocessorMes
3131
}
3232

3333
// Send the Abort state transition to the tool
34-
let mut send_abort_to_tool = |tool_type, message: ToolMessage, update_hints: bool| {
34+
let mut send_abort_to_tool = |tool_type, message: ToolMessage, update_hints_and_cursor: bool| {
3535
if let Some(tool) = tool_data.tools.get_mut(&tool_type) {
3636
tool.process_action(message, (document, document_data, input), responses);
3737

38-
if update_hints {
38+
if update_hints_and_cursor {
3939
tool.process_action(ToolMessage::UpdateHints, (document, document_data, input), responses);
40+
tool.process_action(ToolMessage::UpdateCursor, (document, document_data, input), responses);
4041
}
4142
}
4243
};

editor/src/viewport_tools/tools/ellipse.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::shared::resize::Resize;
22
use crate::document::DocumentMessageHandler;
3+
use crate::frontend::utility_types::MouseCursorIcon;
34
use crate::input::keyboard::{Key, MouseMotion};
45
use crate::input::InputPreprocessorMessageHandler;
56
use crate::message_prelude::*;
@@ -35,11 +36,17 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Ellipse {
3536
return;
3637
}
3738

39+
if action == ToolMessage::UpdateCursor {
40+
self.fsm_state.update_cursor(responses);
41+
return;
42+
}
43+
3844
let new_state = self.fsm_state.transition(action, data.0, data.1, &mut self.data, data.2, responses);
3945

4046
if self.fsm_state != new_state {
4147
self.fsm_state = new_state;
4248
self.fsm_state.update_hints(responses);
49+
self.fsm_state.update_cursor(responses);
4350
}
4451
}
4552

@@ -177,4 +184,8 @@ impl Fsm for EllipseToolFsmState {
177184

178185
responses.push_back(FrontendMessage::UpdateInputHints { hint_data }.into());
179186
}
187+
188+
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
189+
responses.push_back(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Crosshair }.into());
190+
}
180191
}

editor/src/viewport_tools/tools/eyedropper.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::consts::SELECTION_TOLERANCE;
22
use crate::document::DocumentMessageHandler;
3+
use crate::frontend::utility_types::MouseCursorIcon;
34
use crate::input::keyboard::MouseMotion;
45
use crate::input::InputPreprocessorMessageHandler;
56
use crate::message_prelude::*;
@@ -34,11 +35,17 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Eyedropper {
3435
return;
3536
}
3637

38+
if action == ToolMessage::UpdateCursor {
39+
self.fsm_state.update_cursor(responses);
40+
return;
41+
}
42+
3743
let new_state = self.fsm_state.transition(action, data.0, data.1, &mut self.data, data.2, responses);
3844

3945
if self.fsm_state != new_state {
4046
self.fsm_state = new_state;
4147
self.fsm_state.update_hints(responses);
48+
self.fsm_state.update_cursor(responses);
4249
}
4350
}
4451

@@ -127,4 +134,8 @@ impl Fsm for EyedropperToolFsmState {
127134

128135
responses.push_back(FrontendMessage::UpdateInputHints { hint_data }.into());
129136
}
137+
138+
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
139+
responses.push_back(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default }.into());
140+
}
130141
}

editor/src/viewport_tools/tools/fill.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::consts::SELECTION_TOLERANCE;
22
use crate::document::DocumentMessageHandler;
3+
use crate::frontend::utility_types::MouseCursorIcon;
34
use crate::input::keyboard::MouseMotion;
45
use crate::input::InputPreprocessorMessageHandler;
56
use crate::message_prelude::*;
@@ -34,11 +35,17 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Fill {
3435
return;
3536
}
3637

38+
if action == ToolMessage::UpdateCursor {
39+
self.fsm_state.update_cursor(responses);
40+
return;
41+
}
42+
3743
let new_state = self.fsm_state.transition(action, data.0, data.1, &mut self.data, data.2, responses);
3844

3945
if self.fsm_state != new_state {
4046
self.fsm_state = new_state;
4147
self.fsm_state.update_hints(responses);
48+
self.fsm_state.update_cursor(responses);
4249
}
4350
}
4451

@@ -121,4 +128,8 @@ impl Fsm for FillToolFsmState {
121128

122129
responses.push_back(FrontendMessage::UpdateInputHints { hint_data }.into());
123130
}
131+
132+
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
133+
responses.push_back(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default }.into());
134+
}
124135
}

editor/src/viewport_tools/tools/line.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::consts::LINE_ROTATE_SNAP_ANGLE;
22
use crate::document::DocumentMessageHandler;
3+
use crate::frontend::utility_types::MouseCursorIcon;
34
use crate::input::keyboard::{Key, MouseMotion};
45
use crate::input::mouse::ViewportPosition;
56
use crate::input::InputPreprocessorMessageHandler;
@@ -38,11 +39,17 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Line {
3839
return;
3940
}
4041

42+
if action == ToolMessage::UpdateCursor {
43+
self.fsm_state.update_cursor(responses);
44+
return;
45+
}
46+
4147
let new_state = self.fsm_state.transition(action, data.0, data.1, &mut self.data, data.2, responses);
4248

4349
if self.fsm_state != new_state {
4450
self.fsm_state = new_state;
4551
self.fsm_state.update_hints(responses);
52+
self.fsm_state.update_cursor(responses);
4653
}
4754
}
4855

@@ -207,6 +214,10 @@ impl Fsm for LineToolFsmState {
207214

208215
responses.push_back(FrontendMessage::UpdateInputHints { hint_data }.into());
209216
}
217+
218+
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
219+
responses.push_back(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Crosshair }.into());
220+
}
210221
}
211222

212223
fn generate_transform(data: &mut LineToolData, lock: bool, snap: bool, center: bool) -> Message {

editor/src/viewport_tools/tools/navigate.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::document::DocumentMessageHandler;
2+
use crate::frontend::utility_types::MouseCursorIcon;
23
use crate::input::keyboard::{Key, MouseMotion};
34
use crate::input::InputPreprocessorMessageHandler;
45
use crate::message_prelude::*;
@@ -34,11 +35,17 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Navigate {
3435
return;
3536
}
3637

38+
if action == ToolMessage::UpdateCursor {
39+
self.fsm_state.update_cursor(responses);
40+
return;
41+
}
42+
3743
let new_state = self.fsm_state.transition(action, data.0, data.1, &mut self.data, data.2, responses);
3844

3945
if self.fsm_state != new_state {
4046
self.fsm_state = new_state;
4147
self.fsm_state.update_hints(responses);
48+
self.fsm_state.update_cursor(responses);
4249
}
4350
}
4451

@@ -211,4 +218,15 @@ impl Fsm for NavigateToolFsmState {
211218

212219
responses.push_back(FrontendMessage::UpdateInputHints { hint_data }.into());
213220
}
221+
222+
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
223+
let cursor = match *self {
224+
NavigateToolFsmState::Ready => MouseCursorIcon::ZoomIn,
225+
NavigateToolFsmState::Panning => MouseCursorIcon::Grabbing,
226+
NavigateToolFsmState::Tilting => MouseCursorIcon::Default,
227+
NavigateToolFsmState::Zooming => MouseCursorIcon::ZoomIn,
228+
};
229+
230+
responses.push_back(FrontendMessage::UpdateMouseCursor { cursor }.into());
231+
}
214232
}

0 commit comments

Comments
 (0)