Compare commits

..

3 Commits

Author SHA1 Message Date
Enrico Lumetti da73c13f2e Add Viewport up/down scroll and some misc improvements 2021-02-28 19:47:59 +01:00
Enrico Lumetti 3b048896e0 Improve file saving 2021-02-28 19:38:19 +01:00
Enrico Lumetti 390de72aa2 Improve canvas API and fix erasing of multiple elements 2021-02-28 18:49:08 +01:00
4 changed files with 46 additions and 29 deletions

View File

@ -161,11 +161,6 @@ impl Canvas {
self.elements.push_back(element);
}
pub fn remove_element_at(&mut self, index: usize) {
// TODO(enrico): content size should be recomputed
self.elements.remove(index);
}
pub fn elements(&self) -> &Vector<CanvasElement> {
&self.elements
}

View File

@ -24,7 +24,7 @@ use druid::widget::prelude::*;
use druid::widget::{Align, Button, CrossAxisAlignment, Flex, List, SizedBox, WidgetExt};
use druid::{
AppDelegate, AppLauncher, Color, Command, Data, DelegateCtx, Env, FileDialogOptions, FileSpec,
Handled, Lens, LocalizedString, Target, WidgetId, WindowDesc,
Handled, Lens, Target, WidgetId, WindowDesc,
};
use im::Vector;
@ -106,6 +106,7 @@ fn build_ui() -> impl Widget<StilettoState> {
let save_dialog_options = FileDialogOptions::new()
.allowed_types(vec![stlt])
.default_type(stlt);
let save_dialog_options_clone = save_dialog_options.clone();
let open_dialog_options = save_dialog_options.clone();
let save_buttons = Flex::row()
@ -120,19 +121,30 @@ fn build_ui() -> impl Widget<StilettoState> {
ctx.submit_command(Command::new(SCROLL, 30.0, canvas_id));
},
))
.with_child(Button::new("Save").on_click(move |ctx, data: &mut StilettoState, _| {
if data.current_file_path.is_some() {
ctx.submit_command(Command::new(commands::SAVE_FILE, (), Target::Auto));
} else {
ctx.submit_command(Command::new(
druid::commands::SHOW_SAVE_PANEL,
save_dialog_options_clone.clone(),
Target::Auto,
))
}
}))
.with_child(Button::new("Save As").on_click(move |ctx, _, _| {
ctx.submit_command(Command::new(
druid::commands::SHOW_SAVE_PANEL,
save_dialog_options.clone(),
Target::Auto,
))
}))
.with_child(Button::new("Open").on_click(move |ctx, _, _| {
ctx.submit_command(Command::new(
druid::commands::SHOW_OPEN_PANEL,
open_dialog_options.clone(),
Target::Auto,
))
}))
.with_child(Button::new("Save").on_click(move |ctx, _, _| {
ctx.submit_command(Command::new(
druid::commands::SHOW_SAVE_PANEL,
save_dialog_options.clone(),
Target::Auto,
))
}));
let tool_buttons = Flex::row()
@ -176,6 +188,7 @@ fn build_ui() -> impl Widget<StilettoState> {
struct Delegate;
impl AppDelegate<StilettoState> for Delegate {
fn command(
&mut self,
_ctx: &mut DelegateCtx,
@ -186,20 +199,21 @@ impl AppDelegate<StilettoState> for Delegate {
) -> Handled {
use std::fs::File;
if cmd.get(commands::SAVE_FILE).is_some() {
//let path = data.current_file_path.as_ref().unwrap();
// TODO
}
if let Some(file_info) = cmd.get(commands::SAVE_FILE_AS) {
let res_file = File::create(file_info.path());
if cmd.get(commands::SAVE_FILE_AS).is_some() || cmd.get(commands::SAVE_FILE).is_some() {
let mut path_buf = cmd.get(commands::SAVE_FILE_AS)
.map(|file_info| file_info.path().to_path_buf())
.unwrap_or(data.current_file_path.as_ref().cloned().unwrap());
path_buf.set_extension("stlt");
let res_file = File::create(&path_buf);
if let Ok(f) = res_file {
let write_res =
serde_json::to_writer_pretty(f, &data.canvas.get_document_snapshot());
if write_res.is_err() {
warn!("Error while saving: {:?}", write_res.err());
} else {
data.current_file_path = Some(file_info.path().to_path_buf());
info!("Written to file: {}", file_info.path().display());
info!("Written to file: {}", &path_buf.display());
data.current_file_path = Some(path_buf);
}
} else {
warn!("Cannot create file: {:?}", res_file.err());

View File

@ -99,13 +99,20 @@ impl CanvasToolCtx {
(CanvasToolState::Erasing, Event::MouseMove(mouse_event)) => {
let eraser_rect =
druid::Rect::from_center_size(transform * mouse_event.pos, (5.0, 5.0));
let elements = vcanvas.get().find_intersections(eraser_rect);
if !elements.is_empty() {
vcanvas.update(|canvas: &mut Canvas| {
for i in elements {
canvas.remove_element_at(i);
let old_elements = vcanvas.get().elements();
let mut new_elements = old_elements.clone();
new_elements.retain(|elem| {
// Check if the element intersects the eraser rect
if elem.bounding_box().intersect(eraser_rect).area() > 0.0 {
if elem.intersects_rect(eraser_rect) {
return false;
}
}
return true;
});
if new_elements.len() != old_elements.len() {
vcanvas.update(|canvas: &mut Canvas| {
*canvas = Canvas::new_with_elements(new_elements);
});
}
}

View File

@ -25,7 +25,7 @@ use druid::scroll_component::ScrollComponent;
use druid::widget::prelude::*;
use druid::widget::Viewport;
use druid::{Affine, Color, Data, Env, Event};
use druid::{Command, Selector, Target};
use druid::{Selector};
pub const SCROLL: Selector<f64> = Selector::new("scroll_canvas");
@ -182,8 +182,9 @@ impl Widget<CanvasState> for CanvasWidget {
let size = ctx.size();
let rect = size.to_rect();
let page_content_size = data.versioned_canvas.get().content_size();
ctx.fill(rect, &Color::WHITE);
let page_content_size = data.versioned_canvas.get().content_size();
self.viewport.rect = self.viewport.rect.with_size(size);
self.viewport.content_size = druid::Size::new(
self.viewport.rect.x1.max(page_content_size.width),