From c7f04cc6610319911144f25e7f88dfb4a24e9f2e Mon Sep 17 00:00:00 2001 From: rhysd Date: Fri, 10 Nov 2023 10:59:23 +0900 Subject: [PATCH] make some receivers `&mut` and remove unnecessary receivers from traits --- v2/src/dialog.rs | 44 ++++++++++++++++++++++++++++++++++---------- v2/src/renderer.rs | 4 ++-- v2/src/shiba.rs | 29 +++++++++-------------------- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/v2/src/dialog.rs b/v2/src/dialog.rs index 8e9bdf5..81e62ff 100644 --- a/v2/src/dialog.rs +++ b/v2/src/dialog.rs @@ -1,33 +1,57 @@ use crate::config::FileExtensions; +use anyhow::Error; use rfd::{FileDialog, MessageDialog, MessageLevel}; +use std::fmt::Write as _; use std::path::{Path, PathBuf}; -pub trait Dialog: Default { - fn pick_file(&self, dir: &Path, extensions: &FileExtensions) -> Option; - fn pick_dir(&self, dir: &Path) -> Option; - fn alert(&self, title: impl Into, message: impl Into); +#[non_exhaustive] +pub enum DialogMessageLevel { + Error, } -#[derive(Default)] +pub trait Dialog { + fn pick_file(dir: &Path, extensions: &FileExtensions) -> Option; + + fn pick_dir(dir: &Path) -> Option; + + fn message(level: DialogMessageLevel, title: impl Into, body: impl Into); + + fn alert(error: &Error) { + let mut errs = error.chain(); + let title = format!("Error: {}", errs.next().unwrap()); + let mut message = title.clone(); + for err in errs { + write!(message, "\n Caused by: {}", err).unwrap(); + } + log::error!("{}", message); + Self::message(DialogMessageLevel::Error, title, message); + } +} + +// TODO: Consider to set parent window of dialog. rfd provides `set_parent` methods to dialogs. + pub struct SystemDialog; impl Dialog for SystemDialog { - fn pick_file(&self, dir: &Path, extensions: &FileExtensions) -> Option { + fn pick_file(dir: &Path, extensions: &FileExtensions) -> Option { FileDialog::new() .add_filter("Markdown", extensions.as_slice()) .set_directory(dir) .pick_file() } - fn pick_dir(&self, dir: &Path) -> Option { + fn pick_dir(dir: &Path) -> Option { FileDialog::new().set_directory(dir).pick_folder() } - fn alert(&self, title: impl Into, message: impl Into) { + fn message(level: DialogMessageLevel, title: impl Into, body: impl Into) { + let level = match level { + DialogMessageLevel::Error => MessageLevel::Error, + }; MessageDialog::new() - .set_level(MessageLevel::Error) + .set_level(level) .set_title(title.into()) - .set_description(message.into()) + .set_description(body.into()) .show(); } } diff --git a/v2/src/renderer.rs b/v2/src/renderer.rs index 4ab8f84..71166d3 100644 --- a/v2/src/renderer.rs +++ b/v2/src/renderer.rs @@ -209,6 +209,6 @@ pub trait Rendering: Sized { pub trait EventHandler { fn handle_user_event(&mut self, event: UserEvent) -> Result; fn handle_menu_event(&mut self, item: MenuItem) -> Result; - fn handle_exit(&self) -> Result<()>; - fn handle_error(&self, err: Error) -> RenderingFlow; + fn handle_exit(&mut self) -> Result<()>; + fn handle_error(&mut self, err: Error) -> RenderingFlow; } diff --git a/v2/src/shiba.rs b/v2/src/shiba.rs index b71debf..f622e37 100644 --- a/v2/src/shiba.rs +++ b/v2/src/shiba.rs @@ -10,8 +10,8 @@ use crate::renderer::{ use crate::watcher::{PathFilter, Watcher}; use anyhow::{Context as _, Error, Result}; use std::collections::VecDeque; -use std::fmt::Write as _; use std::fs; +use std::marker::PhantomData; use std::mem; use std::path::{Path, PathBuf, MAIN_SEPARATOR}; @@ -189,17 +189,6 @@ impl PreviewContent { } } -fn alert_error(dialog: &D, error: &Error) { - let mut errs = error.chain(); - let title = format!("Error: {}", errs.next().unwrap()); - let mut message = title.clone(); - for err in errs { - write!(message, "\n Caused by: {}", err).unwrap(); - } - log::error!("{}", message); - dialog.alert(title, message); -} - pub struct Shiba { renderer: R::Renderer, opener: O, @@ -208,7 +197,7 @@ pub struct Shiba { config: Config, preview: PreviewContent, init_file: Option, - dialog: D, + _dialog: PhantomData, } impl Shiba @@ -224,7 +213,7 @@ where { fn on_err(err: Error) -> Error { let err = err.context("Could not launch application"); - alert_error(&D::default(), &err); + D::alert(&err); err } let mut rendering = R::new().map_err(on_err::)?; @@ -262,7 +251,7 @@ where config, preview: PreviewContent::default(), init_file, - dialog: D::default(), + _dialog: PhantomData, }) } @@ -310,7 +299,7 @@ where fn open_file(&mut self) -> Result<()> { let extensions = self.config.watch().file_extensions(); let dir = self.config.dialog().default_dir()?; - let file = self.dialog.pick_file(&dir, extensions); + let file = D::pick_file(&dir, extensions); #[cfg(windows)] let file = file.and_then(|p| p.canonicalize().ok()); // Ensure \\? at the head of the path @@ -324,7 +313,7 @@ where fn open_dir(&mut self) -> Result<()> { let dir = self.config.dialog().default_dir()?; - let dir = self.dialog.pick_dir(&dir); + let dir = D::pick_dir(&dir); #[cfg(windows)] let dir = dir.and_then(|p| p.canonicalize().ok()); // Ensure \\? at the head of the path @@ -511,7 +500,7 @@ where Ok(RenderingFlow::Continue) } - fn handle_exit(&self) -> Result<()> { + fn handle_exit(&mut self) -> Result<()> { log::debug!("Handling application exit"); let data_dir = self.config.data_dir(); if self.config.window().restore { @@ -524,8 +513,8 @@ where Ok(()) } - fn handle_error(&self, err: Error) -> RenderingFlow { - alert_error(&self.dialog, &err); + fn handle_error(&mut self, err: Error) -> RenderingFlow { + D::alert(&err); RenderingFlow::Continue } }