Add ToolData and rectangle tool (#64)
This commit is contained in:
parent
fafea371ab
commit
599d478a5c
|
|
@ -1,11 +1,12 @@
|
|||
pub mod operation;
|
||||
|
||||
pub use kurbo::{Circle, Point};
|
||||
pub use kurbo::{Circle, Point, Rect};
|
||||
pub use operation::Operation;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum SvgElement {
|
||||
Circle(Circle),
|
||||
Rect(Rect),
|
||||
}
|
||||
|
||||
impl SvgElement {
|
||||
|
|
@ -14,6 +15,9 @@ impl SvgElement {
|
|||
Self::Circle(c) => {
|
||||
format!(r#"<circle cx="{}" cy="{}" r="{}" style="fill: #fff;" />"#, c.center.x, c.center.y, c.radius)
|
||||
}
|
||||
Self::Rect(r) => {
|
||||
format!(r#"<rect x="{}" y="{}" width="{}" height="{}" style="fill: #fff;" />"#, r.min_x(), r.min_y(), r.width(), r.height())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -36,6 +40,11 @@ impl Document {
|
|||
radius: r,
|
||||
}));
|
||||
|
||||
update_frontend(self.render());
|
||||
}
|
||||
Operation::AddRect { x0, y0, x1, y1 } => {
|
||||
self.svg.push(SvgElement::Rect(Rect::from_points(Point::new(x0, y0), Point::new(x1, y1))));
|
||||
|
||||
update_frontend(self.render());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
pub enum Operation {
|
||||
AddCircle { cx: f64, cy: f64, r: f64 },
|
||||
AddRect { x0: f64, y0: f64, x1: f64, y1: f64 },
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,14 @@ pub struct ViewportPosition {
|
|||
pub y: u32,
|
||||
}
|
||||
|
||||
impl ViewportPosition {
|
||||
pub fn distance(&self, other: &Self) -> f64 {
|
||||
let x_diff = other.x as f64 - self.x as f64;
|
||||
let y_diff = other.y as f64 - self.y as f64;
|
||||
f64::sqrt(x_diff * x_diff + y_diff * y_diff)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
|
||||
pub struct TracePoint {
|
||||
pub mouse_state: MouseState,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::events::MouseKeys;
|
||||
use crate::events::{Event, Response};
|
||||
use crate::events::{MouseKeys, ViewportPosition};
|
||||
use crate::tools::{Fsm, Tool};
|
||||
use crate::Document;
|
||||
use document_core::Operation;
|
||||
|
|
@ -7,13 +7,14 @@ use document_core::Operation;
|
|||
#[derive(Default)]
|
||||
pub struct Ellipse {
|
||||
fsm_state: EllipseToolFsmState,
|
||||
data: EllipseToolData,
|
||||
}
|
||||
|
||||
impl Tool for Ellipse {
|
||||
fn handle_input(&mut self, event: &Event, document: &Document) -> (Vec<Response>, Vec<Operation>) {
|
||||
let mut responses = Vec::new();
|
||||
let mut operations = Vec::new();
|
||||
self.fsm_state = self.fsm_state.transition(event, document, &mut responses, &mut operations);
|
||||
self.fsm_state = self.fsm_state.transition(event, document, &mut self.data, &mut responses, &mut operations);
|
||||
|
||||
(responses, operations)
|
||||
}
|
||||
|
|
@ -23,7 +24,6 @@ impl Tool for Ellipse {
|
|||
enum EllipseToolFsmState {
|
||||
Ready,
|
||||
LmbDown,
|
||||
TransformSelected,
|
||||
}
|
||||
|
||||
impl Default for EllipseToolFsmState {
|
||||
|
|
@ -31,18 +31,29 @@ impl Default for EllipseToolFsmState {
|
|||
EllipseToolFsmState::Ready
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct EllipseToolData {
|
||||
drag_start: ViewportPosition,
|
||||
}
|
||||
|
||||
impl Fsm for EllipseToolFsmState {
|
||||
fn transition(self, event: &Event, document: &Document, responses: &mut Vec<Response>, operations: &mut Vec<Operation>) -> Self {
|
||||
type ToolData = EllipseToolData;
|
||||
|
||||
fn transition(self, event: &Event, document: &Document, data: &mut Self::ToolData, responses: &mut Vec<Response>, operations: &mut Vec<Operation>) -> Self {
|
||||
match (self, event) {
|
||||
(EllipseToolFsmState::Ready, Event::MouseDown(mouse_state)) if mouse_state.mouse_keys.contains(MouseKeys::LEFT) => EllipseToolFsmState::LmbDown,
|
||||
(EllipseToolFsmState::Ready, Event::MouseDown(mouse_state)) if mouse_state.mouse_keys.contains(MouseKeys::LEFT) => {
|
||||
data.drag_start = mouse_state.position;
|
||||
EllipseToolFsmState::LmbDown
|
||||
}
|
||||
|
||||
// TODO - Check for left mouse button
|
||||
(EllipseToolFsmState::LmbDown, Event::MouseUp(mouse_state)) => {
|
||||
let r = data.drag_start.distance(&mouse_state.position);
|
||||
log::info!("draw ellipse with radius: {:.2}", r);
|
||||
operations.push(Operation::AddCircle {
|
||||
cx: mouse_state.position.x as f64,
|
||||
cy: mouse_state.position.y as f64,
|
||||
r: 10.0,
|
||||
cx: data.drag_start.x as f64,
|
||||
cy: data.drag_start.y as f64,
|
||||
r: data.drag_start.distance(&mouse_state.position),
|
||||
});
|
||||
|
||||
EllipseToolFsmState::Ready
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ pub trait Tool {
|
|||
}
|
||||
|
||||
pub trait Fsm {
|
||||
fn transition(self, event: &Event, document: &Document, responses: &mut Vec<Response>, operations: &mut Vec<Operation>) -> Self;
|
||||
type ToolData;
|
||||
fn transition(self, event: &Event, document: &Document, data: &mut Self::ToolData, responses: &mut Vec<Response>, operations: &mut Vec<Operation>) -> Self;
|
||||
}
|
||||
|
||||
pub struct ToolFsmState {
|
||||
|
|
@ -43,7 +44,7 @@ impl Default for ToolFsmState {
|
|||
trace: Trace::new(),
|
||||
primary_color: Color::BLACK,
|
||||
secondary_color: Color::WHITE,
|
||||
active_tool_type: ToolType::Ellipse,
|
||||
active_tool_type: ToolType::Rectangle,
|
||||
tools: gen_tools_hash_map! {
|
||||
Select => select::Select,
|
||||
Crop => crop::Crop,
|
||||
|
|
|
|||
|
|
@ -1,18 +1,68 @@
|
|||
use crate::events::{Event, Response};
|
||||
use crate::tools::Tool;
|
||||
use crate::events::{MouseKeys, ViewportPosition};
|
||||
use crate::tools::{Fsm, Tool};
|
||||
use crate::Document;
|
||||
use document_core::Operation;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Rectangle;
|
||||
pub struct Rectangle {
|
||||
fsm_state: RectangleToolFsmState,
|
||||
data: RectangleToolData,
|
||||
}
|
||||
|
||||
impl Tool for Rectangle {
|
||||
fn handle_input(&mut self, event: &Event, document: &Document) -> (Vec<Response>, Vec<Operation>) {
|
||||
todo!();
|
||||
let mut responses = Vec::new();
|
||||
let mut operations = Vec::new();
|
||||
self.fsm_state = self.fsm_state.transition(event, document, &mut self.data, &mut responses, &mut operations);
|
||||
|
||||
(responses, operations)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum RectangleToolFsmState {
|
||||
Ready,
|
||||
Dragging,
|
||||
LmbDown,
|
||||
}
|
||||
|
||||
impl Default for RectangleToolFsmState {
|
||||
fn default() -> Self {
|
||||
RectangleToolFsmState::Ready
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct RectangleToolData {
|
||||
drag_start: ViewportPosition,
|
||||
}
|
||||
|
||||
impl Fsm for RectangleToolFsmState {
|
||||
type ToolData = RectangleToolData;
|
||||
|
||||
fn transition(self, event: &Event, document: &Document, data: &mut Self::ToolData, responses: &mut Vec<Response>, operations: &mut Vec<Operation>) -> Self {
|
||||
match (self, event) {
|
||||
(RectangleToolFsmState::Ready, Event::MouseDown(mouse_state)) if mouse_state.mouse_keys.contains(MouseKeys::LEFT) => {
|
||||
data.drag_start = mouse_state.position;
|
||||
RectangleToolFsmState::LmbDown
|
||||
}
|
||||
|
||||
// TODO - Check for left mouse button
|
||||
(RectangleToolFsmState::LmbDown, Event::MouseUp(mouse_state)) => {
|
||||
let r = data.drag_start.distance(&mouse_state.position);
|
||||
log::info!("draw rectangle with radius: {:.2}", r);
|
||||
let start = data.drag_start;
|
||||
let end = mouse_state.position;
|
||||
operations.push(Operation::AddRect {
|
||||
x0: start.x as f64,
|
||||
y0: start.y as f64,
|
||||
x1: end.x as f64,
|
||||
y1: end.y as f64,
|
||||
});
|
||||
|
||||
RectangleToolFsmState::Ready
|
||||
}
|
||||
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,13 +7,14 @@ use document_core::Operation;
|
|||
#[derive(Default)]
|
||||
pub struct Select {
|
||||
fsm_state: SelectToolFsmState,
|
||||
data: SelectToolData,
|
||||
}
|
||||
|
||||
impl Tool for Select {
|
||||
fn handle_input(&mut self, event: &Event, document: &Document) -> (Vec<Response>, Vec<Operation>) {
|
||||
let mut responses = Vec::new();
|
||||
let mut operations = Vec::new();
|
||||
self.fsm_state = self.fsm_state.transition(event, document, &mut responses, &mut operations);
|
||||
self.fsm_state = self.fsm_state.transition(event, document, &mut self.data, &mut responses, &mut operations);
|
||||
|
||||
(responses, operations)
|
||||
}
|
||||
|
|
@ -32,8 +33,13 @@ impl Default for SelectToolFsmState {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct SelectToolData;
|
||||
|
||||
impl Fsm for SelectToolFsmState {
|
||||
fn transition(self, event: &Event, document: &Document, responses: &mut Vec<Response>, operations: &mut Vec<Operation>) -> Self {
|
||||
type ToolData = SelectToolData;
|
||||
|
||||
fn transition(self, event: &Event, document: &Document, data: &mut Self::ToolData, responses: &mut Vec<Response>, operations: &mut Vec<Operation>) -> Self {
|
||||
match (self, event) {
|
||||
(SelectToolFsmState::Ready, Event::MouseDown(mouse_state)) if mouse_state.mouse_keys.contains(MouseKeys::LEFT) => SelectToolFsmState::LmbDown,
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue