Cancel in-progress drag with right click or escape key (#119)
This commit is contained in:
parent
3522969fec
commit
52bebfad25
|
|
@ -21,4 +21,4 @@
|
|||
<div id="app"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import { createApp } from "vue";
|
|||
import App from "./App.vue";
|
||||
import { attachResponseHandlerToPage } from "./response-handler";
|
||||
|
||||
document.addEventListener("contextmenu", (e) => e.preventDefault());
|
||||
|
||||
attachResponseHandlerToPage();
|
||||
|
||||
createApp(App).mount("#app");
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ pub fn translate_key(name: &str) -> events::Key {
|
|||
"Shift" => KeyShift,
|
||||
"Control" => KeyControl,
|
||||
"Alt" => KeyAlt,
|
||||
"Escape" => KeyEscape,
|
||||
_ => UnknownKey,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -274,12 +274,12 @@ impl Document {
|
|||
self.work_mount_path = vec![];
|
||||
self.work = Folder::default();
|
||||
self.work_mounted = false;
|
||||
None
|
||||
Some(vec![DocumentResponse::DocumentChanged])
|
||||
}
|
||||
Operation::ClearWorkingFolder => {
|
||||
self.work_operations.clear();
|
||||
self.work = Folder::default();
|
||||
None
|
||||
Some(vec![DocumentResponse::DocumentChanged])
|
||||
}
|
||||
Operation::CommitTransaction => {
|
||||
let mut ops = Vec::new();
|
||||
|
|
|
|||
|
|
@ -187,6 +187,7 @@ pub enum Key {
|
|||
KeyShift,
|
||||
KeyControl,
|
||||
KeyAlt,
|
||||
KeyEscape,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
|
|
|||
|
|
@ -53,14 +53,12 @@ impl Fsm for EllipseToolFsmState {
|
|||
operations.push(Operation::MountWorkingFolder { path: vec![] });
|
||||
EllipseToolFsmState::LmbDown
|
||||
}
|
||||
|
||||
(EllipseToolFsmState::Ready, Event::KeyDown(Key::KeyZ)) => {
|
||||
if let Some(id) = document.root.list_layers().last() {
|
||||
operations.push(Operation::DeleteLayer { path: vec![*id] })
|
||||
}
|
||||
EllipseToolFsmState::Ready
|
||||
}
|
||||
|
||||
(EllipseToolFsmState::LmbDown, Event::MouseMove(mouse_state)) => {
|
||||
data.drag_current = *mouse_state;
|
||||
|
||||
|
|
@ -69,11 +67,11 @@ impl Fsm for EllipseToolFsmState {
|
|||
|
||||
EllipseToolFsmState::LmbDown
|
||||
}
|
||||
|
||||
(EllipseToolFsmState::LmbDown, Event::LmbUp(mouse_state)) => {
|
||||
data.drag_current = mouse_state.position;
|
||||
|
||||
operations.push(Operation::ClearWorkingFolder);
|
||||
// TODO - introduce comparison threshold when operating with canvas coordinates (https://github.com/GraphiteEditor/Graphite/issues/100)
|
||||
if data.drag_start != data.drag_current {
|
||||
operations.push(make_operation(data, tool_data));
|
||||
operations.push(Operation::CommitTransaction);
|
||||
|
|
@ -81,7 +79,12 @@ impl Fsm for EllipseToolFsmState {
|
|||
|
||||
EllipseToolFsmState::Ready
|
||||
}
|
||||
// TODO - simplify with or_patterns when rust 1.53.0 is stable (https://github.com/rust-lang/rust/issues/54883)
|
||||
(EllipseToolFsmState::LmbDown, Event::KeyUp(Key::KeyEscape)) | (EllipseToolFsmState::LmbDown, Event::RmbDown(_)) => {
|
||||
operations.push(Operation::DiscardWorkingFolder);
|
||||
|
||||
EllipseToolFsmState::Ready
|
||||
}
|
||||
(state, Event::KeyDown(Key::KeyShift)) => {
|
||||
data.constrain_to_circle = true;
|
||||
|
||||
|
|
@ -92,7 +95,6 @@ impl Fsm for EllipseToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyUp(Key::KeyShift)) => {
|
||||
data.constrain_to_circle = false;
|
||||
|
||||
|
|
@ -103,7 +105,6 @@ impl Fsm for EllipseToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyDown(Key::KeyAlt)) => {
|
||||
data.center_around_cursor = true;
|
||||
|
||||
|
|
@ -114,7 +115,6 @@ impl Fsm for EllipseToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyUp(Key::KeyAlt)) => {
|
||||
data.center_around_cursor = false;
|
||||
|
||||
|
|
@ -125,7 +125,6 @@ impl Fsm for EllipseToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ impl Fsm for LineToolFsmState {
|
|||
data.drag_current = mouse_state.position;
|
||||
|
||||
operations.push(Operation::ClearWorkingFolder);
|
||||
// TODO - introduce comparison threshold when operating with canvas coordinates (https://github.com/GraphiteEditor/Graphite/issues/100)
|
||||
if data.drag_start != data.drag_current {
|
||||
operations.push(make_operation(data, tool_data));
|
||||
operations.push(Operation::CommitTransaction);
|
||||
|
|
@ -85,7 +86,12 @@ impl Fsm for LineToolFsmState {
|
|||
|
||||
LineToolFsmState::Ready
|
||||
}
|
||||
// TODO - simplify with or_patterns when rust 1.53.0 is stable (https://github.com/rust-lang/rust/issues/54883)
|
||||
(LineToolFsmState::LmbDown, Event::KeyUp(Key::KeyEscape)) | (LineToolFsmState::LmbDown, Event::RmbDown(_)) => {
|
||||
operations.push(Operation::DiscardWorkingFolder);
|
||||
|
||||
LineToolFsmState::Ready
|
||||
}
|
||||
(state, Event::KeyDown(Key::KeyShift)) => {
|
||||
data.snap_angle = true;
|
||||
|
||||
|
|
@ -96,7 +102,6 @@ impl Fsm for LineToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyUp(Key::KeyShift)) => {
|
||||
data.snap_angle = false;
|
||||
|
||||
|
|
@ -107,7 +112,6 @@ impl Fsm for LineToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyDown(Key::KeyControl)) => {
|
||||
data.lock_angle = true;
|
||||
|
||||
|
|
@ -118,7 +122,6 @@ impl Fsm for LineToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyUp(Key::KeyControl)) => {
|
||||
data.lock_angle = false;
|
||||
|
||||
|
|
@ -129,7 +132,6 @@ impl Fsm for LineToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyDown(Key::KeyAlt)) => {
|
||||
data.center_around_cursor = true;
|
||||
|
||||
|
|
@ -140,7 +142,6 @@ impl Fsm for LineToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyUp(Key::KeyAlt)) => {
|
||||
data.center_around_cursor = false;
|
||||
|
||||
|
|
@ -151,7 +152,6 @@ impl Fsm for LineToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,59 +38,75 @@ impl Default for PenToolFsmState {
|
|||
#[derive(Clone, Debug, Default)]
|
||||
struct PenToolData {
|
||||
points: Vec<ViewportPosition>,
|
||||
next_point: ViewportPosition,
|
||||
}
|
||||
|
||||
impl Fsm for PenToolFsmState {
|
||||
type ToolData = PenToolData;
|
||||
|
||||
fn transition(self, event: &Event, document: &Document, tool_data: &DocumentToolData, data: &mut Self::ToolData, _responses: &mut Vec<ToolResponse>, operations: &mut Vec<Operation>) -> Self {
|
||||
let stroke = style::Stroke::new(tool_data.primary_color, 5.);
|
||||
let fill = style::Fill::none();
|
||||
let style = style::PathStyle::new(Some(stroke), Some(fill));
|
||||
|
||||
match (self, event) {
|
||||
(PenToolFsmState::Ready, Event::LmbDown(mouse_state)) => {
|
||||
operations.push(Operation::MountWorkingFolder { path: vec![] });
|
||||
|
||||
data.points.push(mouse_state.position);
|
||||
data.next_point = mouse_state.position;
|
||||
|
||||
PenToolFsmState::LmbDown
|
||||
}
|
||||
(PenToolFsmState::Ready, Event::KeyDown(Key::KeyZ)) => {
|
||||
if let Some(id) = document.root.list_layers().last() {
|
||||
operations.push(Operation::DeleteLayer { path: vec![*id] })
|
||||
}
|
||||
|
||||
PenToolFsmState::Ready
|
||||
}
|
||||
(PenToolFsmState::LmbDown, Event::LmbUp(mouse_state)) => {
|
||||
data.points.push(mouse_state.position);
|
||||
// TODO - introduce comparison threshold when operating with canvas coordinates (https://github.com/GraphiteEditor/Graphite/issues/100)
|
||||
if data.points.last() != Some(&mouse_state.position) {
|
||||
data.points.push(mouse_state.position);
|
||||
data.next_point = mouse_state.position;
|
||||
}
|
||||
|
||||
PenToolFsmState::LmbDown
|
||||
}
|
||||
(PenToolFsmState::LmbDown, Event::MouseMove(mouse_state)) => {
|
||||
let mut points: Vec<_> = data.points.iter().map(|p| (p.x as f64, p.y as f64)).collect();
|
||||
points.push((mouse_state.x as f64, mouse_state.y as f64));
|
||||
data.next_point = *mouse_state;
|
||||
|
||||
operations.push(Operation::ClearWorkingFolder);
|
||||
operations.push(Operation::AddPen {
|
||||
path: vec![],
|
||||
insert_index: -1,
|
||||
points,
|
||||
style,
|
||||
});
|
||||
operations.push(make_operation(data, tool_data, true));
|
||||
|
||||
PenToolFsmState::LmbDown
|
||||
}
|
||||
(PenToolFsmState::LmbDown, Event::KeyDown(Key::KeyEnter)) => {
|
||||
let points = data.points.drain(..).map(|p| (p.x as f64, p.y as f64)).collect();
|
||||
// TODO - simplify with or_patterns when rust 1.53.0 is stable (https://github.com/rust-lang/rust/issues/54883)
|
||||
(PenToolFsmState::LmbDown, Event::KeyDown(Key::KeyEnter)) | (PenToolFsmState::LmbDown, Event::KeyDown(Key::KeyEscape)) | (PenToolFsmState::LmbDown, Event::RmbDown(_)) => {
|
||||
operations.push(Operation::ClearWorkingFolder);
|
||||
operations.push(Operation::AddPen {
|
||||
path: vec![],
|
||||
insert_index: -1,
|
||||
points,
|
||||
style,
|
||||
});
|
||||
operations.push(Operation::CommitTransaction);
|
||||
|
||||
if data.points.len() >= 2 {
|
||||
operations.push(make_operation(data, tool_data, false));
|
||||
operations.push(Operation::CommitTransaction);
|
||||
} else {
|
||||
operations.push(Operation::DiscardWorkingFolder);
|
||||
}
|
||||
|
||||
data.points.clear();
|
||||
|
||||
PenToolFsmState::Ready
|
||||
}
|
||||
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_operation(data: &PenToolData, tool_data: &DocumentToolData, show_preview: bool) -> Operation {
|
||||
let mut points: Vec<(f64, f64)> = data.points.iter().map(|p| (p.x as f64, p.y as f64)).collect();
|
||||
if show_preview {
|
||||
points.push((data.next_point.x as f64, data.next_point.y as f64))
|
||||
}
|
||||
Operation::AddPen {
|
||||
path: vec![],
|
||||
insert_index: -1,
|
||||
points,
|
||||
style: style::PathStyle::new(Some(style::Stroke::new(tool_data.primary_color, 5.)), Some(style::Fill::none())),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ impl Fsm for RectangleToolFsmState {
|
|||
data.drag_current = mouse_state.position;
|
||||
|
||||
operations.push(Operation::ClearWorkingFolder);
|
||||
// TODO - introduce comparison threshold when operating with canvas coordinates (https://github.com/GraphiteEditor/Graphite/issues/100)
|
||||
if data.drag_start != data.drag_current {
|
||||
operations.push(make_operation(data, tool_data));
|
||||
operations.push(Operation::CommitTransaction);
|
||||
|
|
@ -78,7 +79,12 @@ impl Fsm for RectangleToolFsmState {
|
|||
|
||||
RectangleToolFsmState::Ready
|
||||
}
|
||||
// TODO - simplify with or_patterns when rust 1.53.0 is stable (https://github.com/rust-lang/rust/issues/54883)
|
||||
(RectangleToolFsmState::LmbDown, Event::KeyUp(Key::KeyEscape)) | (RectangleToolFsmState::LmbDown, Event::RmbDown(_)) => {
|
||||
operations.push(Operation::DiscardWorkingFolder);
|
||||
|
||||
RectangleToolFsmState::Ready
|
||||
}
|
||||
(state, Event::KeyDown(Key::KeyShift)) => {
|
||||
data.constrain_to_square = true;
|
||||
|
||||
|
|
@ -89,7 +95,6 @@ impl Fsm for RectangleToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyUp(Key::KeyShift)) => {
|
||||
data.constrain_to_square = false;
|
||||
|
||||
|
|
@ -100,7 +105,6 @@ impl Fsm for RectangleToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyDown(Key::KeyAlt)) => {
|
||||
data.center_around_cursor = true;
|
||||
|
||||
|
|
@ -111,7 +115,6 @@ impl Fsm for RectangleToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyUp(Key::KeyAlt)) => {
|
||||
data.center_around_cursor = false;
|
||||
|
||||
|
|
@ -122,7 +125,6 @@ impl Fsm for RectangleToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ impl Fsm for ShapeToolFsmState {
|
|||
(ShapeToolFsmState::LmbDown, Event::LmbUp(mouse_state)) => {
|
||||
data.drag_current = mouse_state.position;
|
||||
operations.push(Operation::ClearWorkingFolder);
|
||||
// TODO - introduce comparison threshold when operating with canvas coordinates (https://github.com/GraphiteEditor/Graphite/issues/100)
|
||||
if data.drag_start != data.drag_current {
|
||||
operations.push(make_operation(data, tool_data));
|
||||
operations.push(Operation::CommitTransaction);
|
||||
|
|
@ -80,7 +81,12 @@ impl Fsm for ShapeToolFsmState {
|
|||
|
||||
ShapeToolFsmState::Ready
|
||||
}
|
||||
// TODO - simplify with or_patterns when rust 1.53.0 is stable (https://github.com/rust-lang/rust/issues/54883)
|
||||
(ShapeToolFsmState::LmbDown, Event::KeyUp(Key::KeyEscape)) | (ShapeToolFsmState::LmbDown, Event::RmbDown(_)) => {
|
||||
operations.push(Operation::DiscardWorkingFolder);
|
||||
|
||||
ShapeToolFsmState::Ready
|
||||
}
|
||||
(state, Event::KeyDown(Key::KeyShift)) => {
|
||||
data.constrain_to_square = true;
|
||||
|
||||
|
|
@ -91,7 +97,6 @@ impl Fsm for ShapeToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyUp(Key::KeyShift)) => {
|
||||
data.constrain_to_square = false;
|
||||
|
||||
|
|
@ -102,7 +107,6 @@ impl Fsm for ShapeToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyDown(Key::KeyAlt)) => {
|
||||
data.center_around_cursor = true;
|
||||
|
||||
|
|
@ -113,7 +117,6 @@ impl Fsm for ShapeToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
(state, Event::KeyUp(Key::KeyAlt)) => {
|
||||
data.center_around_cursor = false;
|
||||
|
||||
|
|
@ -124,7 +127,6 @@ impl Fsm for ShapeToolFsmState {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue