Implement basic circle stamping (#53)

This commit is contained in:
T0mstone 2021-03-29 01:44:34 +02:00 committed by Keavon Chambers
parent 5c13279d91
commit d037e956e8
10 changed files with 85 additions and 46 deletions

7
Cargo.lock generated
View File

@ -49,7 +49,6 @@ name = "graphite-document-core"
version = "0.1.0"
dependencies = [
"kurbo",
"svg_fmt",
]
[[package]]
@ -132,12 +131,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
[[package]]
name = "svg_fmt"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2"
[[package]]
name = "syn"
version = "1.0.64"

View File

@ -17,7 +17,9 @@
@mousedown="canvasMouseDown"
@mouseup="canvasMouseUp"
@mousemove="canvasMouseMove"
></LayoutCol>
>
<svg></svg>
</LayoutCol>
</LayoutRow>
</LayoutCol>
</template>
@ -65,6 +67,11 @@
.canvas {
background: #111;
flex: 1 1 100%;
svg {
width: 100%;
height: 100%;
}
}
}
}

View File

@ -1,3 +1,3 @@
export function update_canvas() {
console.log("update_canvas")
export function update_canvas(svg) {
document.querySelector(".canvas svg").innerHTML = svg;
}

View File

@ -9,7 +9,7 @@ use std::cell::RefCell;
use wasm_bindgen::prelude::*;
// the thread_local macro provides a way to initialize static variables with non-constant functions
thread_local! {pub static EDITOR_STATE: RefCell<Editor> = RefCell::new(Editor::new(Box::new(handle_response)))}
thread_local! { pub static EDITOR_STATE: RefCell<Editor> = RefCell::new(Editor::new(Box::new(handle_response))) }
#[wasm_bindgen(start)]
pub fn init() {
@ -18,13 +18,13 @@ pub fn init() {
fn handle_response(response: Response) {
match response {
Response::UpdateCanvas => update_canvas(),
Response::UpdateCanvas { document } => update_canvas(document),
}
}
#[wasm_bindgen(module = "/../src/wasm-callback-processor.js")]
extern "C" {
fn update_canvas();
fn update_canvas(svg: String);
}
#[wasm_bindgen]

View File

@ -35,7 +35,7 @@ pub fn on_mouse_down(x: u32, y: u32, mouse_keys: u8) -> Result<(), JsValue> {
#[wasm_bindgen]
pub fn on_mouse_up(x: u32, y: u32, mouse_keys: u8) -> Result<(), JsValue> {
let mouse_keys = events::MouseKeys::from_bits(mouse_keys).expect("invalid modifier keys");
let ev = events::Event::MouseDown(events::MouseState {
let ev = events::Event::MouseUp(events::MouseState {
position: events::CanvasPosition { x, y },
mouse_keys,
});

View File

@ -9,3 +9,4 @@ repository = "https://github.com/GraphiteEditor/Graphite"
license = "Apache-2.0"
[dependencies]
kurbo = "0.8.0"

View File

@ -1,7 +1,27 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
pub use kurbo::{Circle, Point};
#[derive(Debug, Clone, PartialEq)]
pub enum SvgElement {
Circle(Circle),
}
impl SvgElement {
pub fn render(&self) -> String {
match self {
Self::Circle(c) => {
format!(r#"<circle cx="{}" cy="{}" r="{}" style="fill: #fff;" />"#, c.center.x, c.center.y, c.radius)
}
}
}
}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct Document {
pub svg: Vec<SvgElement>,
}
impl Document {
pub fn render(&self) -> String {
self.svg.iter().map(|element| element.render()).collect::<Vec<_>>().join("\n")
}
}

View File

@ -22,7 +22,7 @@ pub enum Event {
#[derive(Debug, Clone)]
#[repr(C)]
pub enum Response {
UpdateCanvas,
UpdateCanvas { document: String },
}
#[derive(Debug, Clone, Default)]

View File

@ -1,6 +1,6 @@
pub mod events;
use crate::tools::ToolState;
use crate::{Color, EditorError};
use crate::{Color, EditorError, EditorState};
use document_core::{Circle, Point, SvgElement};
use events::{Event, Response};
pub type Callback = Box<dyn Fn(Response)>;
@ -9,60 +9,68 @@ pub struct Dispatcher {
}
impl Dispatcher {
pub fn handle_event(&self, tool_state: &mut ToolState, event: Event) -> Result<(), EditorError> {
pub fn handle_event(&self, state: &mut EditorState, event: Event) -> Result<(), EditorError> {
match event {
Event::SelectTool(tool_type) => {
tool_state.active_tool = tool_type;
state.tools.active_tool = tool_type;
Ok(())
}
Event::SelectPrimaryColor(color) => {
tool_state.primary_color = color;
state.tools.primary_color = color;
Ok(())
}
Event::SelectSecondaryColor(color) => {
tool_state.secondary_color = color;
state.tools.secondary_color = color;
Ok(())
}
Event::SwapColors => {
std::mem::swap(&mut tool_state.primary_color, &mut tool_state.secondary_color);
std::mem::swap(&mut state.tools.primary_color, &mut state.tools.secondary_color);
Ok(())
}
Event::ResetColors => {
tool_state.primary_color = Color::BLACK;
tool_state.secondary_color = Color::WHITE;
state.tools.primary_color = Color::BLACK;
state.tools.secondary_color = Color::WHITE;
Ok(())
}
Event::MouseDown(mouse_state) => {
tool_state.mouse_state = mouse_state;
state.tools.mouse_state = mouse_state;
// the state has changed so we add a trace point
tool_state.record_trace_point();
state.tools.record_trace_point();
self.emit_response(Response::UpdateCanvas);
// self.emit_response(Response::UpdateCanvas { document: state.document.render() });
Ok(())
}
Event::MouseUp(mouse_state) => {
tool_state.mouse_state = mouse_state;
state.tools.mouse_state = mouse_state;
// the state has changed so we add a trace point
tool_state.record_trace_point();
state.tools.record_trace_point();
self.emit_response(Response::UpdateCanvas);
state.document.svg.push(SvgElement::Circle(Circle {
center: Point {
x: mouse_state.position.x as f64,
y: mouse_state.position.y as f64,
},
radius: 10.0,
}));
self.emit_response(Response::UpdateCanvas { document: state.document.render() });
Ok(())
}
Event::MouseMovement(pos) => {
tool_state.mouse_state.position = pos;
tool_state.record_trace_point();
state.tools.mouse_state.position = pos;
state.tools.record_trace_point();
Ok(())
}
Event::ModifierKeyDown(mod_keys) => {
tool_state.mod_keys = mod_keys;
state.tools.mod_keys = mod_keys;
// the state has changed so we add a trace point
tool_state.record_trace_point();
state.tools.record_trace_point();
Ok(())
}
Event::ModifierKeyUp(mod_keys) => {
tool_state.mod_keys = mod_keys;
state.tools.mod_keys = mod_keys;
// the state has changed so we add a trace point
tool_state.record_trace_point();
state.tools.record_trace_point();
Ok(())
}
Event::KeyPress(key) => todo!(),

View File

@ -17,25 +17,35 @@ pub use dispatcher::events;
pub use dispatcher::Callback;
use dispatcher::Dispatcher;
use document_core::Document;
use tools::ToolState;
use workspace::Workspace;
// TODO: serialize with serde to save the current editor state
pub struct Editor {
pub struct EditorState {
tools: ToolState,
workspace: Workspace,
document: Document,
}
// TODO: serialize with serde to save the current editor state
pub struct Editor {
state: EditorState,
dispatcher: Dispatcher,
}
impl Editor {
pub fn new(callback: Callback) -> Self {
Self {
tools: ToolState::new(),
workspace: Workspace::new(),
state: EditorState {
tools: ToolState::new(),
workspace: Workspace::new(),
document: Document::default(),
},
dispatcher: Dispatcher::new(callback),
}
}
pub fn handle_event(&mut self, event: events::Event) -> Result<(), EditorError> {
self.dispatcher.handle_event(&mut self.tools, event)
self.dispatcher.handle_event(&mut self.state, event)
}
}