Implement basic circle stamping (#53)
This commit is contained in:
parent
5c13279d91
commit
d037e956e8
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
export function update_canvas() {
|
||||
console.log("update_canvas")
|
||||
export function update_canvas(svg) {
|
||||
document.querySelector(".canvas svg").innerHTML = svg;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,3 +9,4 @@ repository = "https://github.com/GraphiteEditor/Graphite"
|
|||
license = "Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
kurbo = "0.8.0"
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ pub enum Event {
|
|||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub enum Response {
|
||||
UpdateCanvas,
|
||||
UpdateCanvas { document: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
|
|
|||
|
|
@ -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!(),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue