WIP: Eraser implementation #7
47
src/main.rs
47
src/main.rs
|
|
@ -16,10 +16,15 @@
|
|||
|
||||
use druid::kurbo::{BezPath, Rect};
|
||||
use druid::widget::prelude::*;
|
||||
use druid::{AppLauncher, Color, Data, Event, LocalizedString, WindowDesc};
|
||||
use druid::{AppLauncher, Color, Data, Lens, Event, LocalizedString, WidgetExt, WindowDesc};
|
||||
|
||||
use stiletto::{CanvasElement, VersionedCanvas, Canvas};
|
||||
|
||||
#[derive(Clone, Data, PartialEq)]
|
||||
enum CanvasToolType {
|
||||
Pen,
|
||||
Eraser
|
||||
}
|
||||
|
enrico marked this conversation as resolved
|
||||
|
||||
// Tools that can be used to interact with the canvas
|
||||
#[derive(Clone, Data)]
|
||||
|
|
@ -35,6 +40,33 @@ impl CanvasTool {
|
|||
fn new_eraser() -> CanvasTool {
|
||||
CanvasTool::Eraser { eraser_rect: None }
|
||||
}
|
||||
|
enrico marked this conversation as resolved
enrico
commented
Nice Nice
|
||||
|
||||
fn tool_type(&self) -> CanvasToolType {
|
||||
match self {
|
||||
CanvasTool::Pen { current_element: _ } => CanvasToolType::Pen,
|
||||
CanvasTool::Eraser { eraser_rect: _ } => CanvasToolType::Eraser,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CanvasToolLens;
|
||||
|
||||
impl Lens<CanvasData, CanvasToolType> for CanvasToolLens {
|
||||
fn with<R, F: FnOnce(&CanvasToolType) -> R>(&self, data: &CanvasData, f: F) -> R {
|
||||
f(&data.current_tool.tool_type())
|
||||
}
|
||||
|
||||
fn with_mut<R, F: FnOnce(&mut CanvasToolType) -> R>(&self, data: &mut CanvasData, f: F) -> R {
|
||||
let mut curr_type = data.current_tool.tool_type();
|
||||
let result = f(&mut curr_type);
|
||||
|
||||
match curr_type {
|
||||
CanvasToolType::Pen => data.current_tool = CanvasTool::new_pen(),
|
||||
CanvasToolType::Eraser => data.current_tool = CanvasTool::new_eraser(),
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Data)]
|
||||
|
|
@ -48,9 +80,7 @@ impl CanvasData {
|
|||
self.current_element.is_some()
|
||||
}*/
|
||||
|
||||
fn set_tool(&mut self, tool: CanvasTool) {
|
||||
self.current_tool = tool;
|
||||
}
|
||||
const CURRENT_TOOL_LENS: CanvasToolLens = CanvasToolLens;
|
||||
|
||||
fn perform_undo(&mut self) {
|
||||
self.elements.undo();
|
||||
|
|
@ -133,6 +163,7 @@ impl CanvasData {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
struct CanvasWidget;
|
||||
|
||||
impl Widget<CanvasData> for CanvasWidget {
|
||||
|
|
@ -231,15 +262,17 @@ impl Widget<CanvasData> for CanvasWidget {
|
|||
}
|
||||
|
||||
fn build_ui() -> impl Widget<CanvasData> {
|
||||
use druid::widget::{Align, Button, CrossAxisAlignment, Flex, SizedBox};
|
||||
use druid::widget::{Align, Button, RadioGroup, CrossAxisAlignment, Flex, SizedBox};
|
||||
|
||||
let radio_group = RadioGroup::new(vec![("Pen", CanvasToolType::Pen), ("Eraser", CanvasToolType::Eraser)]);
|
||||
|
||||
|
||||
let toolbar = Flex::row()
|
||||
.cross_axis_alignment(CrossAxisAlignment::Center)
|
||||
.with_spacer(30.0)
|
||||
.with_child(Button::new("Undo").on_click(|_ctx, data: &mut CanvasData, _env| data.perform_undo()))
|
||||
.with_child(Button::new("Redo").on_click(|_ctx, data: &mut CanvasData, _env| data.perform_redo()))
|
||||
.with_child(Button::new("Pen").on_click(|_ctx, data: &mut CanvasData, _env| data.set_tool(CanvasTool::new_pen())))
|
||||
.with_child(Button::new("Eraser").on_click(|_ctx, data: &mut CanvasData, _env| data.set_tool(CanvasTool::new_eraser())));
|
||||
.with_child(radio_group.lens(CanvasData::CURRENT_TOOL_LENS));
|
||||
|
||||
Flex::column()
|
||||
.cross_axis_alignment(CrossAxisAlignment::Center)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
When does
the current path being drawnmake sense?I felt a little uncomfortable keeping this in CanvasData, because there is no current path being drawn when we erase. Probably with the state machine we can achieve a cleaner vision, though.
It still fits the CanvasData, because it is a piece of data associated to the Canvas (indeed, the currently drawn item). When there is no currently drawn item, is set to None; for the time being, current_element != None is the result of is_drawing()