Compare commits

..

No commits in common. "cb8bc30a150cc798db2d28f4d9b65924fdc6641f" and "e51f6c431c1a418d6bc8e64726695b072dde77fc" have entirely different histories.

11 changed files with 630 additions and 459 deletions

781
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -7,26 +7,25 @@ default-run = "stiletto"
[dependencies] [dependencies]
log = "0.4" log = "0.4"
druid = { version = "0.7", features = ["im", "svg"] } druid = { version = "0.7.0", features = ["im", "svg"] }
im = { version = "*" } im = { version = "*" }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_bare = "0.3.0" serde_bare = "0.3.0"
serde_json = "1.0" serde_json = "1.0"
clap = "3.1" clap = "3.0.0-beta.2"
[target.'cfg(target_os="linux")'.dependencies.gtk] [target.'cfg(target_os="linux")'.dependencies.gtk]
version = "0.14" version = "0.9.2"
features = ["v3_22"] features = ["v3_22"]
[target.'cfg(target_os="linux")'.dependencies.gio] [target.'cfg(target_os="linux")'.dependencies.gio]
version = "0.14" version = "0.9.1"
features = ["v2_56"] features = ["v2_56"]
[target.'cfg(target_os="linux")'.dependencies.gdk] [target.'cfg(target_os="linux")'.dependencies.gdk]
version = "0.14" version = "0.13.2"
features = ["v3_22"] features = ["v3_22"]
[patch.crates-io] [patch.crates-io]
#druid = { git = "https://github.com/jneem/druid", branch = "pointer", features = ["im", "svg"] } druid = { git = "https://github.com/jneem/druid", branch = "pointer", features = ["im", "svg"] }
druid = { path= "../druid/druid/" }

View File

@ -14,39 +14,35 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use clap::{Arg, Command}; use clap::{Arg, App};
use stiletto::migration::open_stiletto_document; use stiletto::migration::open_stiletto_document;
use std::fs::File; use std::fs::File;
use std::path::PathBuf; use std::path::PathBuf;
fn main() { fn main() {
let matches = Command::new("Stiletto Migration CLI") let matches = App::new("Stiletto Migration CLI")
.version("0.1.0") .version("0.1.0")
.author("Stiletto Authors") .author("Stiletto Authors")
.about("Migrate a stlt file to the latest version") .about("Migrate a stlt file to the latest version")
.arg( .arg(Arg::new("INPUT")
Arg::new("INPUT") .about("Sets the input file to use")
.help("Sets the input file to use") .required(true)
.required(true) .index(1))
.index(1), .arg(Arg::new("OUTPUT")
) .about("Sets the output file to use")
.arg( .required(true)
Arg::new("OUTPUT") .index(2))
.help("Sets the output file to use")
.required(true)
.index(2),
)
.get_matches(); .get_matches();
let input_path = matches.value_of("INPUT").unwrap(); let input_path = matches.value_of("INPUT").unwrap();
let output_path = matches.value_of("OUTPUT").unwrap(); let output_path = matches.value_of("OUTPUT").unwrap();
let out_file = File::create(&output_path).expect("Cannot create output fle"); let out_file = File::create(&output_path).expect("Cannot create output fle");
let result = open_stiletto_document(&PathBuf::from(&input_path)); let result = open_stiletto_document(&PathBuf::from(&input_path));
if let Ok(document) = result { if let Ok(document) = result {
let snapshot = document.migrate_to_latest(); let snapshot = document.migrate_to_latest();
snapshot.to_writer(out_file); snapshot.to_writer(out_file);
} }
} }

View File

@ -27,6 +27,12 @@ pub struct Path {
pub kurbo_path: druid::kurbo::BezPath, pub kurbo_path: druid::kurbo::BezPath,
} }
#[derive(Serialize, Deserialize)]
#[serde(remote = "druid::Color")]
enum ColorDef {
Rgba32(u32),
}
struct Interval { struct Interval {
start_pos: f64, start_pos: f64,
end_pos: f64, end_pos: f64,
@ -80,29 +86,11 @@ pub enum CanvasElement {
Freehand { Freehand {
path: Path, path: Path,
thickness: f64, thickness: f64,
#[serde( #[serde(with = "ColorDef")]
serialize_with = "serialize_color",
deserialize_with = "deserialize_color"
)]
stroke_color: druid::Color, stroke_color: druid::Color,
}, },
} }
fn serialize_color<S>(c: &druid::Color, ser: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
ser.serialize_u32(c.as_rgba_u32())
}
fn deserialize_color<'de, D>(de: D) -> Result<druid::Color, D::Error>
where
D: Deserializer<'de>,
{
let c = u32::deserialize(de)?;
Ok(druid::Color::from_rgba32_u32(c))
}
impl CanvasElement { impl CanvasElement {
pub fn bounding_box(&self) -> druid::Rect { pub fn bounding_box(&self) -> druid::Rect {
match self { match self {
@ -205,16 +193,11 @@ impl Serialize for Path {
{ {
use druid::kurbo::PathEl; use druid::kurbo::PathEl;
serializer.collect_seq( serializer.collect_seq(self.kurbo_path.iter().filter_map(|path_el| match path_el {
self.kurbo_path PathEl::MoveTo(pt) => Some(Into::<(f64, f64)>::into(pt)),
.iter() PathEl::LineTo(pt) => Some(Into::<(f64, f64)>::into(pt)),
.filter_map(|path_el| match path_el { _ => None,
PathEl::MoveTo(pt) => Some(Into::<(f64, f64)>::into(pt)), }).collect::<Vec<(f64, f64)>>())
PathEl::LineTo(pt) => Some(Into::<(f64, f64)>::into(pt)),
_ => None,
})
.collect::<Vec<(f64, f64)>>(),
)
} }
} }

View File

@ -19,9 +19,9 @@ use std::vec::Vec;
pub mod canvas; pub mod canvas;
pub mod history; pub mod history;
pub mod migration;
pub mod tool; pub mod tool;
pub mod widget; pub mod widget;
pub mod migration;
pub mod commands { pub mod commands {
use druid::Selector; use druid::Selector;

View File

@ -24,20 +24,23 @@ use druid::widget::prelude::*;
use druid::widget::{ use druid::widget::{
Align, Button, Controller, CrossAxisAlignment, Flex, List, SizedBox, WidgetExt, Align, Button, Controller, CrossAxisAlignment, Flex, List, SizedBox, WidgetExt,
}; };
use druid::gesture::DruidGestureRecognizer;
use druid::{ use druid::{
AppDelegate, AppLauncher, Color, Command, Data, DelegateCtx, Env, FileDialogOptions, FileSpec, AppDelegate, AppLauncher, Color, Command, Data, DelegateCtx, Env, FileDialogOptions, FileSpec,
Handled, Lens, Target, WidgetId, WindowDesc, Handled, Lens, PointerEventPolicy, Target, WidgetId, WindowDesc,
}; };
use im::Vector; use im::Vector;
use stiletto::tool::CanvasToolParams; use stiletto::tool::CanvasToolParams;
use stiletto::widget::tool_ctx::CanvasToolCtx; use stiletto::widget::tool_ctx::{CanvasToolCtx};
use stiletto::widget::{build_simple_tool_widget, CanvasState, CanvasToolIconState, CanvasWidget}; use stiletto::widget::{build_simple_tool_widget, CanvasState, CanvasToolIconState, CanvasWidget};
use stiletto::DocumentSnapshot; use stiletto::DocumentSnapshot;
pub fn main() { pub fn main() {
let window = WindowDesc::new(build_ui()) let window = WindowDesc::new(build_ui)
.set_pointer_event_policy(PointerEventPolicy::UseMixedApi)
.set_gesture_recognizer(Box::new(DruidGestureRecognizer::new()))
.window_size((1024.0, 1400.0)) .window_size((1024.0, 1400.0))
.title(|data: &StilettoState, _env: &Env| { .title(|data: &StilettoState, _env: &Env| {
let doc_name = if let Some(path) = &data.current_file_path { let doc_name = if let Some(path) = &data.current_file_path {
@ -77,7 +80,7 @@ pub fn main() {
current_file_path: None, current_file_path: None,
}; };
AppLauncher::with_window(window) AppLauncher::with_window(window)
.log_to_console() .use_simple_logger()
.delegate(Delegate) .delegate(Delegate)
.launch(canvas_data) .launch(canvas_data)
.expect("launch failed"); .expect("launch failed");
@ -137,19 +140,17 @@ fn build_ui() -> impl Widget<StilettoState> {
ctx.submit_command(Command::new(CanvasWidget::SCROLL, 30.0, canvas_id)); ctx.submit_command(Command::new(CanvasWidget::SCROLL, 30.0, canvas_id));
}, },
)) ))
.with_child( .with_child(Button::new("Save").on_click(move |ctx, data: &mut StilettoState, _| {
Button::new("Save").on_click(move |ctx, data: &mut StilettoState, _| { if data.current_file_path.is_some() {
if data.current_file_path.is_some() { ctx.submit_command(Command::new(commands::SAVE_FILE, (), Target::Auto));
ctx.submit_command(Command::new(commands::SAVE_FILE, (), Target::Auto)); } else {
} else { ctx.submit_command(Command::new(
ctx.submit_command(Command::new( druid::commands::SHOW_SAVE_PANEL,
druid::commands::SHOW_SAVE_PANEL, save_dialog_options_clone.clone(),
save_dialog_options_clone.clone(), Target::Auto,
Target::Auto, ))
)) }
} }))
}),
)
.with_child(Button::new("Save As").on_click(move |ctx, _, _| { .with_child(Button::new("Save As").on_click(move |ctx, _, _| {
ctx.submit_command(Command::new( ctx.submit_command(Command::new(
druid::commands::SHOW_SAVE_PANEL, druid::commands::SHOW_SAVE_PANEL,
@ -276,7 +277,8 @@ impl AppDelegate<StilettoState> for Delegate {
let res_file = File::create(&path_buf); let res_file = File::create(&path_buf);
if let Ok(f) = res_file { if let Ok(f) = res_file {
let write_res = data.canvas.get_document_snapshot().to_writer(f); let write_res =
data.canvas.get_document_snapshot().to_writer(f);
if write_res.is_err() { if write_res.is_err() {
warn!("Error while saving: {:?}", write_res.err()); warn!("Error while saving: {:?}", write_res.err());
} else { } else {

View File

@ -47,9 +47,7 @@ impl StilettoDocument {
pub fn migrate_to_next(self) -> StilettoDocument { pub fn migrate_to_next(self) -> StilettoDocument {
match self { match self {
StilettoDocument::DocumentSnapshot0_1(snapshot) => { StilettoDocument::DocumentSnapshot0_1(snapshot) => StilettoDocument::DocumentSnapshot0_2(snapshot) ,
StilettoDocument::DocumentSnapshot0_2(snapshot)
}
StilettoDocument::DocumentSnapshot0_2(_) => self, StilettoDocument::DocumentSnapshot0_2(_) => self,
} }
} }
@ -62,11 +60,12 @@ impl StilettoDocument {
assert!(matches!(self, StilettoDocument::DocumentSnapshot0_2(_))); assert!(matches!(self, StilettoDocument::DocumentSnapshot0_2(_)));
match self { match self {
StilettoDocument::DocumentSnapshot0_2(snapshot) => snapshot, StilettoDocument::DocumentSnapshot0_2(snapshot) => snapshot,
_ => panic!("Wrong Document Snapshot Version"), _ => panic!("Wrong Document Snapshot Version")
} }
} }
} }
impl fmt::Display for MigrationError { impl fmt::Display for MigrationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self { match &self {
@ -75,11 +74,10 @@ impl fmt::Display for MigrationError {
MigrationError::IoError(e) => e.fmt(f), MigrationError::IoError(e) => e.fmt(f),
MigrationError::UnexpectedVersion(major, minor, e_major, e_minor) => { MigrationError::UnexpectedVersion(major, minor, e_major, e_minor) => {
write!( write!(
f, f, "Unexpected version ({}, {}): was expecting ({}, {})",
"Unexpected version ({}, {}): was expecting ({}, {})",
major, minor, e_major, e_minor major, minor, e_major, e_minor
) )
} },
} }
} }
} }
@ -116,12 +114,12 @@ impl From<serde_bare::Error> for MigrationError {
fn open_0_1(path: &PathBuf) -> Result<StilettoDocument, MigrationError> { fn open_0_1(path: &PathBuf) -> Result<StilettoDocument, MigrationError> {
let f = File::open(path)?; let f = File::open(path)?;
let document_snapshot: DocumentSnapshot = serde_json::from_reader(f)?; let document_snapshot: DocumentSnapshot = serde_json::from_reader(f)?;
if document_snapshot.format_version_major != 0 || document_snapshot.format_version_minor != 1 { if document_snapshot.format_version_major != 0 ||
document_snapshot.format_version_minor != 1 {
Err(MigrationError::UnexpectedVersion( Err(MigrationError::UnexpectedVersion(
document_snapshot.format_version_major, document_snapshot.format_version_major,
document_snapshot.format_version_minor, document_snapshot.format_version_minor,
0, 0, 1
1,
)) ))
} else { } else {
Ok(StilettoDocument::DocumentSnapshot0_1(document_snapshot)) Ok(StilettoDocument::DocumentSnapshot0_1(document_snapshot))
@ -141,3 +139,4 @@ pub fn open_stiletto_document(path: &PathBuf) -> Result<StilettoDocument, Migrat
open_0_2(path) open_0_2(path)
} }

View File

@ -16,7 +16,7 @@
use druid::{Color, Data}; use druid::{Color, Data};
#[derive(Clone, Data, Debug)] #[derive(Clone, Data)]
pub enum CanvasToolParams { pub enum CanvasToolParams {
Pen { thickness: f64, color: Color }, Pen { thickness: f64, color: Color },
Eraser, Eraser,

View File

@ -16,17 +16,18 @@
use im::Vector; use im::Vector;
use super::tool_ctx::CanvasToolCtx; use super::tool_ctx::{CanvasToolCtx};
use crate::canvas::Canvas; use crate::canvas::Canvas;
use crate::history::VersionedCanvas; use crate::history::VersionedCanvas;
use crate::DocumentSnapshot; use crate::DocumentSnapshot;
use druid::kurbo::Point;
use druid::scroll_component::ScrollComponent; use druid::scroll_component::ScrollComponent;
use druid::widget::prelude::*; use druid::widget::prelude::*;
use druid::widget::Viewport; use druid::widget::Viewport;
use druid::kurbo::Point;
use druid::{Affine, Color, Data, Env, Event, PointerType, Selector}; use druid::{Affine, Color, Data, Env, Event, PointerType, Selector};
#[derive(Clone, Data)] #[derive(Clone, Data)]
pub struct CanvasState { pub struct CanvasState {
versioned_canvas: VersionedCanvas, versioned_canvas: VersionedCanvas,
@ -86,13 +87,7 @@ impl CanvasState {
&mut self.tool_ctx &mut self.tool_ctx
} }
pub fn handle_event( pub fn handle_event(&mut self, ctx: &mut EventCtx, event: &Event, transform: Affine, env: &Env) {
&mut self,
ctx: &mut EventCtx,
event: &Event,
transform: Affine,
env: &Env,
) {
self.tool_ctx self.tool_ctx
.handle_event(ctx, event, &mut self.versioned_canvas, transform, env); .handle_event(ctx, event, &mut self.versioned_canvas, transform, env);
} }
@ -109,8 +104,7 @@ impl CanvasWidget {
CanvasWidget { CanvasWidget {
viewport: Viewport { viewport: Viewport {
content_size: Size::new(0.0, 0.0), content_size: Size::new(0.0, 0.0),
view_origin: Point::new(0.0, 0.0), rect: druid::Rect::new(0.0, 0.0, 0.0, 0.0),
view_size: Size::new(0.0, 0.0),
}, },
widget_size: Size::new(0.0, 0.0), widget_size: Size::new(0.0, 0.0),
scroll_component: ScrollComponent::new(), scroll_component: ScrollComponent::new(),
@ -118,14 +112,16 @@ impl CanvasWidget {
} }
fn widget_to_viewport(&self) -> Affine { fn widget_to_viewport(&self) -> Affine {
if !self.viewport.view_size.is_empty() && !self.widget_size.is_empty() { let viewport_rect_size = self.viewport.rect.size();
let scale_x = self.viewport.view_size.width / self.widget_size.width; if !viewport_rect_size.is_empty() && !self.widget_size.is_empty() {
let scale_y = self.viewport.view_size.height / self.widget_size.height; let scale_x = viewport_rect_size.width / self.widget_size.width;
Affine::translate(self.viewport.view_origin.to_vec2()) let scale_y = viewport_rect_size.height / self.widget_size.height;
* Affine::scale_non_uniform(scale_x, scale_y) Affine::translate(self.viewport.rect.origin().to_vec2())
* Affine::scale_non_uniform(scale_x, scale_y)
} else { } else {
Affine::scale(1.0) // identity Affine::scale(1.0) // identity
} }
} }
pub const SCROLL: Selector<f64> = Selector::new("scroll_canvas"); pub const SCROLL: Selector<f64> = Selector::new("scroll_canvas");
@ -158,25 +154,44 @@ impl Widget<CanvasState> for CanvasWidget {
viewport_transform = Some(Affine::translate((-30.0, 0.0))); viewport_transform = Some(Affine::translate((-30.0, 0.0)));
} }
} }
Event::MouseDown(pointer_event) => { Event::MouseDown(mouse_event) => {
toggle_eraser_event = true; toggle_eraser_event = true;
enable_temporary_erasing = pointer_event.pointer_type == PointerType::Eraser; enable_temporary_erasing = false; //mouse_event.pointer_type == PointerType::Eraser;
} }
Event::MouseMove(pointer_event) => { Event::MouseMove(mouse_event) => {
toggle_eraser_event = true; toggle_eraser_event = true;
enable_temporary_erasing = pointer_event.pointer_type == PointerType::Eraser; enable_temporary_erasing = false; //mouse_event.pointer_type == PointerType::Eraser;
} }
Event::MouseUp(pointer_event) => { Event::MouseUp(mouse_event) => {
toggle_eraser_event = true; toggle_eraser_event = true;
enable_temporary_erasing = pointer_event.pointer_type == PointerType::Eraser; enable_temporary_erasing = false; //mouse_event.pointer_type == PointerType::Eraser;
} }
Event::Wheel(pointer) => { Event::Wheel(mouse) => {
let transform = self.widget_to_viewport(); let transform = self.widget_to_viewport();
viewport_transform = Some(Affine::translate( viewport_transform = Some(
(pointer.wheel_delta.to_point()).to_vec2(), Affine::translate(
)); (mouse.wheel_delta.to_point()).to_vec2()
)
);
}
Event::GestureZoom { zoom, center } => {
let transform = self.widget_to_viewport();
let diff = (transform * *center).to_vec2()
- self.viewport.rect.center().to_vec2();
viewport_transform = Some(
Affine::scale(1.0/(1.0 + zoom))
);
log::debug!("{:#?}", viewport_transform);
}
Event::GesturePan(vec2) => {
let transform = self.widget_to_viewport();
viewport_transform = Some(
Affine::translate(
(vec2.to_point()).to_vec2()
)
);
} }
_ => {} _ => {}
} }
// TODO: the first eraser toggle is not handled // TODO: the first eraser toggle is not handled
@ -190,8 +205,8 @@ impl Widget<CanvasState> for CanvasWidget {
} else { } else {
data.handle_event(ctx, event, self.widget_to_viewport(), env); data.handle_event(ctx, event, self.widget_to_viewport(), env);
} }
if let Some(transform) = viewport_transform { if let Some(transform) = viewport_transform {
let mut new_rect = transform.transform_rect_bbox(self.viewport.view_rect()); let mut new_rect = transform.transform_rect_bbox(self.viewport.rect);
if new_rect.x0 <= 0f64 { if new_rect.x0 <= 0f64 {
new_rect.x1 -= new_rect.x0; new_rect.x1 -= new_rect.x0;
new_rect.x0 = 0f64; new_rect.x0 = 0f64;
@ -200,7 +215,7 @@ impl Widget<CanvasState> for CanvasWidget {
new_rect.y1 -= new_rect.y0; new_rect.y1 -= new_rect.y0;
new_rect.y0 = 0f64; new_rect.y0 = 0f64;
} }
self.viewport.view_origin = new_rect.origin(); self.viewport.rect = new_rect;
self.scroll_component self.scroll_component
.reset_scrollbar_fade(|d| ctx.request_timer(d), env); .reset_scrollbar_fade(|d| ctx.request_timer(d), env);
ctx.request_paint(); ctx.request_paint();
@ -269,14 +284,13 @@ impl Widget<CanvasState> for CanvasWidget {
let page_content_size = data.versioned_canvas.get().content_size(); let page_content_size = data.versioned_canvas.get().content_size();
let transform = self.widget_to_viewport(); let transform = self.widget_to_viewport();
//self.viewport.rect = self.viewport.rect =
// transform.transform_rect_bbox(rect) transform.transform_rect_bbox(rect)
// .with_origin(self.viewport.rect.origin()); .with_origin(self.viewport.rect.origin());
self.viewport.view_size = transform.transform_rect_bbox(rect).size();
self.viewport.content_size = druid::Size::new( self.viewport.content_size = druid::Size::new(
self.viewport.view_rect().x1.max(page_content_size.width), self.viewport.rect.x1.max(page_content_size.width),
self.viewport.view_rect().y1.max(page_content_size.height), self.viewport.rect.y1.max(page_content_size.height),
); );
//log::debug!("{:#?}", &self.viewport); //log::debug!("{:#?}", &self.viewport);

View File

@ -1,6 +1,6 @@
pub mod canvas; pub mod canvas;
pub mod tool_ctx;
pub mod tool_icon; pub mod tool_icon;
pub mod tool_ctx;
pub use canvas::*; pub use canvas::*;
pub use tool_icon::*; pub use tool_icon::*;

View File

@ -14,14 +14,14 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::tool::{CanvasToolParams, CanvasToolType};
use crate::canvas::{Canvas, CanvasElement}; use crate::canvas::{Canvas, CanvasElement};
use crate::history::VersionedCanvas; use crate::history::VersionedCanvas;
use crate::tool::{CanvasToolParams, CanvasToolType};
use druid::kurbo::BezPath; use druid::kurbo::BezPath;
use druid::{Affine, Data, Env, Event, EventCtx, PaintCtx, PointerButton, PointerEvent}; use druid::{Affine, Data, Env, Event, EventCtx, MouseButton, MouseEvent, PaintCtx};
#[derive(Clone, Data, Debug)] #[derive(Clone, Data)]
pub enum CanvasToolState { pub enum CanvasToolState {
Idle, Idle,
DrawingFreehand { DrawingFreehand {
@ -46,14 +46,9 @@ impl CanvasToolParams {
} }
} }
fn pressed(pointer_event: &PointerEvent) -> bool { fn pressed(mouse_event: &MouseEvent) -> bool {
dbg!(&pointer_event); mouse_event.buttons.contains(MouseButton::Left)
dbg!( || mouse_event.button == MouseButton::Left
pointer_event.buttons.contains(PointerButton::Left)
|| pointer_event.button == PointerButton::Left
);
pointer_event.buttons.contains(PointerButton::Left)
|| pointer_event.button == PointerButton::Left
} }
impl CanvasToolCtx { impl CanvasToolCtx {
@ -87,13 +82,13 @@ impl CanvasToolCtx {
_env: &Env, _env: &Env,
) { ) {
match (&mut self.state, event) { match (&mut self.state, event) {
(CanvasToolState::Idle, Event::MouseDown(pointer_event)) if pressed(pointer_event) => { (CanvasToolState::Idle, Event::MouseDown(mouse_event)) if pressed(mouse_event) => {
self.state = CanvasToolState::Erasing; self.state = CanvasToolState::Erasing;
ctx.set_handled(); ctx.set_handled();
} }
(CanvasToolState::Erasing, Event::MouseMove(pointer_event)) => { (CanvasToolState::Erasing, Event::MouseMove(mouse_event)) if pressed(mouse_event) => {
let eraser_rect = let eraser_rect =
druid::Rect::from_center_size(transform * pointer_event.pos, (5.0, 5.0)); druid::Rect::from_center_size(transform * mouse_event.pos, (5.0, 5.0));
let old_elements = vcanvas.get().elements(); let old_elements = vcanvas.get().elements();
let mut new_elements = old_elements.clone(); let mut new_elements = old_elements.clone();
new_elements.retain(|elem| { new_elements.retain(|elem| {
@ -112,7 +107,7 @@ impl CanvasToolCtx {
} }
ctx.set_handled(); ctx.set_handled();
} }
(CanvasToolState::Erasing, Event::MouseUp(pointer_event)) if pressed(pointer_event) => { (CanvasToolState::Erasing, Event::MouseUp(mouse_event)) if pressed(mouse_event) => {
self.state = CanvasToolState::Idle; self.state = CanvasToolState::Idle;
ctx.set_handled(); ctx.set_handled();
} }
@ -129,9 +124,9 @@ impl CanvasToolCtx {
_env: &Env, _env: &Env,
) { ) {
match (&mut self.state, event) { match (&mut self.state, event) {
(CanvasToolState::Idle, Event::MouseDown(pointer_event)) if pressed(pointer_event) => { (CanvasToolState::Idle, Event::MouseDown(mouse_event)) if pressed(mouse_event) => {
let mut kurbo_path = BezPath::new(); let mut kurbo_path = BezPath::new();
kurbo_path.move_to((pointer_event.pos.x, pointer_event.pos.y)); kurbo_path.move_to((mouse_event.pos.x, mouse_event.pos.y));
if let CanvasToolParams::Pen { thickness, color } = &self.initial_params { if let CanvasToolParams::Pen { thickness, color } = &self.initial_params {
self.state = CanvasToolState::DrawingFreehand { self.state = CanvasToolState::DrawingFreehand {
pen_params: self.initial_params.clone(), pen_params: self.initial_params.clone(),
@ -149,33 +144,31 @@ impl CanvasToolCtx {
ref mut current_path, ref mut current_path,
.. ..
}, },
Event::MouseMove(pointer_event), Event::MouseMove(mouse_event),
) => { ) => if pressed(mouse_event) {
// TODO(enrico): investigate why mouse move doesn't carry buttons anymore if let CanvasElement::Freehand { ref mut path, .. } = current_path {
//if pressed(pointer_event) { path.kurbo_path
let CanvasElement::Freehand { ref mut path, .. } = current_path; .line_to((mouse_event.pos.x, mouse_event.pos.y));
path.kurbo_path }
.line_to((pointer_event.pos.x, pointer_event.pos.y));
ctx.set_handled(); ctx.set_handled();
//}
} }
(CanvasToolState::DrawingFreehand { .. }, Event::MouseUp(pointer_event)) (CanvasToolState::DrawingFreehand { .. }, Event::MouseUp(mouse_event)) if pressed(mouse_event) => {
if pressed(pointer_event) =>
{
vcanvas.update(move |canvas: &mut Canvas| { vcanvas.update(move |canvas: &mut Canvas| {
let current_state = std::mem::replace(&mut self.state, CanvasToolState::Idle); let current_state = std::mem::replace(&mut self.state, CanvasToolState::Idle);
if let CanvasToolState::DrawingFreehand { current_path, .. } = current_state { if let CanvasToolState::DrawingFreehand { current_path, .. } = current_state {
let CanvasElement::Freehand { if let CanvasElement::Freehand {
mut path, mut path,
thickness, thickness,
stroke_color, stroke_color,
} = current_path; } = current_path
path.kurbo_path.apply_affine(transform); {
canvas.add_element(CanvasElement::Freehand { path.kurbo_path.apply_affine(transform);
path, canvas.add_element(CanvasElement::Freehand {
thickness, path,
stroke_color, thickness,
}); stroke_color,
});
}
} }
}); });
ctx.set_handled(); ctx.set_handled();