Use file dialogs to open/save files

This commit is contained in:
Enrico Lumetti 2020-11-09 18:59:02 +01:00
parent e6885125af
commit cfa925da2f
1 changed files with 71 additions and 26 deletions

View File

@ -14,15 +14,18 @@
// 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 log::warn; use log::{info, warn};
use druid::im::{vector, Vector}; use druid::im::{vector, Vector};
use druid::kurbo::BezPath; use druid::kurbo::BezPath;
use druid::widget::prelude::*; use druid::widget::prelude::*;
use druid::{AppLauncher, Color, Data, Event, LocalizedString, WindowDesc}; use druid::{AppLauncher, Color, Data, Event, LocalizedString, WindowDesc, AppDelegate, Target, Env, DelegateCtx, FileDialogOptions, FileSpec, Command};
use druid::commands;
use stiletto::{CanvasElement, VersionedCanvas, Canvas, DocumentSnapshot}; use stiletto::{CanvasElement, VersionedCanvas, Canvas, DocumentSnapshot};
struct Delegate;
#[derive(Clone, Data)] #[derive(Clone, Data)]
struct CanvasData { struct CanvasData {
current_element: Option<CanvasElement>, current_element: Option<CanvasElement>,
@ -89,7 +92,7 @@ impl Widget<CanvasData> for CanvasWidget {
data.elements.update(move |canvas: &Canvas| -> Canvas { data.elements.update(move |canvas: &Canvas| -> Canvas {
let mut new_canvas = canvas.clone(); let mut new_canvas = canvas.clone();
new_canvas.push_back(current_element); new_canvas.push_back(current_element);
return new_canvas; new_canvas
}); });
} }
@ -173,38 +176,38 @@ fn build_ui() -> impl Widget<CanvasData> {
) )
.with_child(Button::new("Redo").on_click(|_ctx: &mut EventCtx, data: &mut CanvasData, _env: &Env| data.perform_redo())); .with_child(Button::new("Redo").on_click(|_ctx: &mut EventCtx, data: &mut CanvasData, _env: &Env| data.perform_redo()));
let stlt = FileSpec::new("Stiletto notebook", &["stlt"]);
let save_dialog_options = FileDialogOptions::new()
.allowed_types(vec![stlt])
.default_type(stlt);
let open_dialog_options = save_dialog_options.clone();
let save_buttons = Flex::row() let save_buttons = Flex::row()
.cross_axis_alignment(CrossAxisAlignment::Center) .cross_axis_alignment(CrossAxisAlignment::Center)
.with_child( .with_child(
Button::new("Open") Button::new("Open")
.on_click(|_ctx, data: &mut CanvasData, _env| { .on_click(move |ctx, _, _| {
use std::fs::File; ctx.submit_command(
Command::new(
if let Ok(f) = File::open("test.stlt") { druid::commands::SHOW_OPEN_PANEL,
let res_snapshot: Result<DocumentSnapshot, serde_json::Error> = serde_json::from_reader(f); open_dialog_options.clone(),
if let Ok(document_snapshot) = res_snapshot { ),
data.set_from_snapshot(document_snapshot); None,
} else { )
warn!("didn't work: {:?}", res_snapshot.err());
}
}
})) }))
.with_child( .with_child(
Button::new("Save") Button::new("Save")
.on_click(|_ctx, data: &mut CanvasData, _env| { .on_click(move |ctx, _, _| {
use std::fs::File; ctx.submit_command(
Command::new(
let res_file = File::create("test.stlt"); druid::commands::SHOW_SAVE_PANEL,
if let Ok(f) = res_file { save_dialog_options.clone(),
let write_res = serde_json::to_writer_pretty(f, &data.get_document_snapshot()); ),
if write_res.is_err() { None,
warn!("Error while saving: {:?}", write_res.err()); )
}
} else {
warn!("Cannot create file: {:?}", res_file.err());
}
})); }));
let toolbar = Flex::row() let toolbar = Flex::row()
.cross_axis_alignment(CrossAxisAlignment::Center) .cross_axis_alignment(CrossAxisAlignment::Center)
.with_spacer(30.0) .with_spacer(30.0)
@ -231,6 +234,48 @@ pub fn main() {
}; };
AppLauncher::with_window(window) AppLauncher::with_window(window)
.use_simple_logger() .use_simple_logger()
.delegate(Delegate)
.launch(canvas_data) .launch(canvas_data)
.expect("launch failed"); .expect("launch failed");
} }
impl AppDelegate<CanvasData> for Delegate {
fn command(
&mut self,
_ctx: &mut DelegateCtx,
_target: Target,
cmd: &Command,
data: &mut CanvasData,
_env: &Env,
) -> bool {
use std::fs::File;
if let Some(Some(file_info)) = cmd.get(commands::SAVE_FILE) {
let res_file = File::create(file_info.path());
if let Ok(f) = res_file {
let write_res = serde_json::to_writer_pretty(f, &data.get_document_snapshot());
if write_res.is_err() {
warn!("Error while saving: {:?}", write_res.err());
} else {
info!("Written to file: {}", file_info.path().display());
}
} else {
warn!("Cannot create file: {:?}", res_file.err());
}
return true;
}
if let Some(file_info) = cmd.get(commands::OPEN_FILE) {
if let Ok(f) = File::open(file_info.path()) {
let res_snapshot: Result<DocumentSnapshot, serde_json::Error> = serde_json::from_reader(f);
if let Ok(document_snapshot) = res_snapshot {
data.set_from_snapshot(document_snapshot);
info!("Loaded file {}", file_info.path().display());
} else {
warn!("didn't work: {:?}", res_snapshot.err());
}
}
return true;
}
false
}
}