use std::{fmt::Debug, path::Path};
use document_state::{Document, FileFormat, SaveError};
pub enum SaveOutcome {
Saved,
Cancelled,
Failed(String),
}
pub enum OpenOutcome<T: FileFormat + Clone> {
Opened(Box<Document<T>>),
Cancelled,
Failed(String),
}
pub fn save_to<T: FileFormat + Clone>(document: &mut Document<T>, path: &Path) -> SaveOutcome {
match document.save_as(path.to_path_buf()) {
Ok(()) => SaveOutcome::Saved,
Err(error) => SaveOutcome::Failed(format!("failed to save: {error}")),
}
}
pub fn save_in_place<T: FileFormat + Clone>(document: &mut Document<T>) -> Option<SaveOutcome> {
match document.save() {
Ok(()) => Some(SaveOutcome::Saved),
Err(SaveError::NoPath) => None,
Err(SaveError::Write(error)) => {
Some(SaveOutcome::Failed(format!("failed to save: {error}")))
}
}
}
#[cfg(feature = "dialogs")]
pub fn save<T: FileFormat + Clone>(document: &mut Document<T>) -> SaveOutcome {
save_in_place(document).unwrap_or_else(|| save_as(document))
}
#[cfg(feature = "dialogs")]
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;
};
save_to(document, &path)
}
#[cfg(feature = "dialogs")]
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())),
}
}