use document_state::{Document, FileFormat, SaveError};
use std::fmt::Debug;
use std::path::Path;
pub enum SaveOutcome {
Saved,
Cancelled,
Failed(String),
}
pub enum OpenOutcome<T: FileFormat + Clone> {
Opened(Box<Document<T>>),
Cancelled,
Failed(String),
}
pub fn save<T: FileFormat + Clone>(document: &mut Document<T>) -> SaveOutcome {
match document.save() {
Ok(()) => SaveOutcome::Saved,
Err(SaveError::NoPath) => save_as(document),
Err(SaveError::Write(error)) => SaveOutcome::Failed(format!("failed to save: {error}")),
}
}
pub fn save_as<T: FileFormat + Clone>(document: &mut Document<T>) -> SaveOutcome {
let Some(path) = rfd::FileDialog::new()
.set_directory(document.dialog_directory())
.save_file()
else {
return SaveOutcome::Cancelled;
};
match document.save_as(path) {
Ok(()) => SaveOutcome::Saved,
Err(error) => SaveOutcome::Failed(format!("failed to save: {error}")),
}
}
pub fn open<T: FileFormat + Clone>(current: &Document<T>) -> OpenOutcome<T>
where
T::Error: Debug,
{
let Some(path) = rfd::FileDialog::new()
.set_directory(current.dialog_directory())
.pick_file()
else {
return OpenOutcome::Cancelled;
};
open_path(&path)
}
#[must_use]
pub fn open_path<T: FileFormat + Clone>(path: &Path) -> OpenOutcome<T>
where
T::Error: Debug,
{
match Document::<T>::open(path) {
Ok(document) => OpenOutcome::Opened(Box::new(document)),
Err(error) => OpenOutcome::Failed(format!("failed to open {}: {error}", path.display())),
}
}