diff --git a/src/app.rs b/src/app.rs index 131a2b8..3d47736 100644 --- a/src/app.rs +++ b/src/app.rs @@ -8,7 +8,7 @@ use crate::i18n::I18n; use crate::receipt::Receipt; use crate::theme::Theme; use crate::views::AppView; -use eframe::egui::{self, Context}; +use eframe::egui::{self, Context, Image}; use std::collections::HashSet; use std::path::Path; @@ -80,9 +80,28 @@ impl eframe::App for ChecksumApp { .show(ctx, |ui| { self.theme.set_visuals(ui.visuals_mut()); self.update_status(ctx); - let view = self.view.to_owned(); - view.display(self, ui); - view.handle_dropped_files(self, ctx); + + egui::Frame::none() + .inner_margin(crate::UI_MARGIN_LARGE) + .show(ui, |ui| { + let (logo_name, logo_bytes) = self.theme.get_logo_bytes(); + ui.add(Image::from_bytes(logo_name, logo_bytes).fit_to_original_size(1.0)); + }); + + egui::ScrollArea::both().show(ui, |ui| { + egui::Frame::none() + .inner_margin(egui::Margin { + left: crate::UI_MARGIN_LARGE, + right: crate::UI_MARGIN_LARGE, + top: crate::UI_MARGIN_NONE, + bottom: crate::UI_MARGIN_LARGE, + }) + .show(ui, |ui| { + let view = self.view.to_owned(); + view.display(self, ui); + view.handle_dropped_files(self, ctx); + }); + }); }); } } diff --git a/src/main.rs b/src/main.rs index 4c0162d..26aaa4d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,6 +39,14 @@ const NB_FILES_START: u32 = 1; const WIN_WIDTH: f32 = 720.0; const WIN_HEIGHT: f32 = 345.0; +const MAIN_ROUNDING: f32 = 7.0; +const UI_BTN_PADDING_H: f32 = 10.0; +const UI_BTN_PADDING_V: f32 = 6.0; +const UI_MARGIN_LARGE: f32 = 32.0; +const UI_MARGIN_MEDIUM: f32 = 16.0; +const UI_MARGIN_SMALL: f32 = 8.0; +const UI_MARGIN_NONE: f32 = 0.0; + fn main() { let config = config::Config::init(); let viewport = eframe::egui::ViewportBuilder::default() diff --git a/src/theme.rs b/src/theme.rs index 71aabbd..2664a8f 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -13,8 +13,6 @@ use eframe::egui::{self, FontFamily, FontId, RichText, TextStyle}; use serde::{Deserialize, Serialize}; pub const AVAILABLE_THEMES: &[Theme] = &[Theme::Dark, Theme::Light]; -pub const LARGE_PADDING: f32 = 6.0; -pub const MAIN_ROUNDING: f32 = 7.0; #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] @@ -145,7 +143,7 @@ impl Theme { pub fn get_main_frame(&self) -> egui::Frame { egui::Frame::default() - .inner_margin(32.0) + .inner_margin(crate::UI_MARGIN_NONE) .fill(Color::MainFrameBackground.get(*self)) } @@ -171,7 +169,7 @@ impl Theme { width: 1.0, color: Color::MainText.get(*self), }; - visuals.widgets.noninteractive.rounding = MAIN_ROUNDING.into(); + visuals.widgets.noninteractive.rounding = crate::MAIN_ROUNDING.into(); visuals.widgets.noninteractive.fg_stroke = egui::Stroke { width: 12.0, color: Color::MainText.get(*self), @@ -184,7 +182,7 @@ impl Theme { width: 1.0, color: Color::ButtonBorder.get(*self), }; - visuals.widgets.inactive.rounding = MAIN_ROUNDING.into(); + visuals.widgets.inactive.rounding = crate::MAIN_ROUNDING.into(); visuals.widgets.inactive.fg_stroke = egui::Stroke { width: 12.0, color: Color::ButtonText.get(*self), @@ -197,7 +195,7 @@ impl Theme { width: 1.0, color: Color::ButtonBorderHovered.get(*self), }; - visuals.widgets.hovered.rounding = MAIN_ROUNDING.into(); + visuals.widgets.hovered.rounding = crate::MAIN_ROUNDING.into(); visuals.widgets.hovered.fg_stroke = egui::Stroke { width: 12.0, color: Color::ButtonTextHovered.get(*self), @@ -210,7 +208,7 @@ impl Theme { width: 1.0, color: Color::ButtonBorderHovered.get(*self), }; - visuals.widgets.active.rounding = MAIN_ROUNDING.into(); + visuals.widgets.active.rounding = crate::MAIN_ROUNDING.into(); visuals.widgets.active.fg_stroke = egui::Stroke { width: 12.0, color: Color::ButtonTextHovered.get(*self), @@ -223,7 +221,7 @@ impl Theme { width: 1.0, color: Color::ButtonBorderHovered.get(*self), }; - visuals.widgets.open.rounding = MAIN_ROUNDING.into(); + visuals.widgets.open.rounding = crate::MAIN_ROUNDING.into(); visuals.widgets.open.fg_stroke = egui::Stroke { width: 12.0, color: Color::ButtonTextHovered.get(*self), diff --git a/src/theme/infobox.rs b/src/theme/infobox.rs index cfa5606..8db57a2 100644 --- a/src/theme/infobox.rs +++ b/src/theme/infobox.rs @@ -4,8 +4,8 @@ use eframe::egui; const INFOBOX_BORDER_SIZE: f32 = 1.0; const INFOBOX_ICON_SIZE: f32 = 20.0; const INFOBOX_MAIN_LEFT_BORDER_SIZE: f32 = 13.0; -const INFOBOX_PADDING: f32 = crate::theme::LARGE_PADDING; -const INFOBOX_ROUNDING: f32 = crate::theme::MAIN_ROUNDING; +const INFOBOX_PADDING: f32 = crate::UI_MARGIN_SMALL; +const INFOBOX_ROUNDING: f32 = crate::MAIN_ROUNDING; #[derive(Clone, Copy, Debug)] pub enum InfoBoxType { diff --git a/src/views.rs b/src/views.rs index fde8c2e..cee7bde 100644 --- a/src/views.rs +++ b/src/views.rs @@ -5,11 +5,6 @@ mod check_errors; mod config; mod main; -const UI_BTN_PADDING_H: f32 = 10.0; -const UI_BTN_PADDING_V: f32 = 6.0; -const UI_EXTRA_SPACE: f32 = 8.0; -const UI_MARGIN_LARGE: f32 = 16.0; - #[derive(Clone)] pub enum AppView { CheckErrors, diff --git a/src/views/check_errors.rs b/src/views/check_errors.rs index 9e032ef..4bea2b5 100644 --- a/src/views/check_errors.rs +++ b/src/views/check_errors.rs @@ -2,14 +2,14 @@ use crate::app::ChecksumApp; use crate::checker::CheckResult; use crate::theme::Button; use crate::views::AppView; -use eframe::egui::{self, Image}; +use eframe::egui; macro_rules! file_error { ($app: ident, $ui: ident, $lst: expr, $title: literal) => { if !$lst.is_empty() { - $ui.add_space(super::UI_MARGIN_LARGE); + $ui.add_space(crate::UI_MARGIN_MEDIUM); $ui.label($app.theme.title(&$app.i18n.msg($title))); - $ui.add_space(super::UI_EXTRA_SPACE); + $ui.add_space(crate::UI_MARGIN_SMALL); for f in &$lst { $ui.label(f.path.display().to_string()); } @@ -18,14 +18,9 @@ macro_rules! file_error { } pub fn display(app: &mut ChecksumApp, ui: &mut egui::Ui) { - let (logo_name, logo_bytes) = app.theme.get_logo_bytes(); - let spacing = ui.spacing_mut(); app.default_padding = spacing.button_padding; - spacing.button_padding = egui::vec2(super::UI_BTN_PADDING_H, super::UI_BTN_PADDING_V); - - ui.add(Image::from_bytes(logo_name, logo_bytes).fit_to_original_size(1.0)); - ui.add_space(super::UI_MARGIN_LARGE); + spacing.button_padding = egui::vec2(crate::UI_BTN_PADDING_H, crate::UI_BTN_PADDING_V); if let Some(CheckResult::CheckErrors(err)) = &app.file_check_result { file_error!(app, ui, err.invalid_ctn_file, "title_invalid_ctn_file"); @@ -34,7 +29,7 @@ pub fn display(app: &mut ChecksumApp, ui: &mut egui::Ui) { file_error!(app, ui, err.missing_receipt, "title_missing_receipt"); } - ui.add_space(super::UI_MARGIN_LARGE); + ui.add_space(crate::UI_MARGIN_MEDIUM); if ui .add(Button::new().text(app.i18n.msg("back")).render()) .clicked() diff --git a/src/views/config.rs b/src/views/config.rs index 154fc71..fd2c0dc 100644 --- a/src/views/config.rs +++ b/src/views/config.rs @@ -4,22 +4,21 @@ use crate::config::Config; use crate::i18n::I18n; use crate::theme::{Button, Icon}; use crate::views::AppView; -use eframe::egui::{self, Image}; +use eframe::egui; pub fn display(app: &mut ChecksumApp, ui: &mut egui::Ui) { let mut new_config = get_config(app); - let (logo_name, logo_bytes) = app.theme.get_logo_bytes(); - ui.add(Image::from_bytes(logo_name, logo_bytes).fit_to_original_size(1.0)); - ui.add_space(super::UI_MARGIN_LARGE); - ui.add_space(super::UI_MARGIN_LARGE); - + ui.add_space(crate::UI_MARGIN_MEDIUM); ui.label(app.theme.title(&app.i18n.msg("config_title"))); - ui.add_space(super::UI_MARGIN_LARGE); + ui.add_space(crate::UI_MARGIN_MEDIUM); egui::Grid::new("header_grid") .num_columns(2) - .spacing(egui::Vec2 { x: 0.0, y: 6.0 }) + .spacing(egui::Vec2 { + x: crate::UI_MARGIN_NONE, + y: crate::UI_MARGIN_SMALL, + }) .show(ui, |ui| { // Content file name let default_content_file_name = app.i18n.msg("content_file_name"); @@ -184,10 +183,10 @@ pub fn display(app: &mut ChecksumApp, ui: &mut egui::Ui) { let spacing = ui.spacing_mut(); app.default_padding = spacing.button_padding; - spacing.button_padding = egui::vec2(super::UI_BTN_PADDING_H, super::UI_BTN_PADDING_V); + spacing.button_padding = egui::vec2(crate::UI_BTN_PADDING_H, crate::UI_BTN_PADDING_V); app.tmp_config = Some(new_config.clone()); - ui.add_space(super::UI_MARGIN_LARGE); + ui.add_space(crate::UI_MARGIN_MEDIUM); ui.horizontal(|ui| { if ui .add(Button::new().text(app.i18n.msg("apply")).render()) diff --git a/src/views/main.rs b/src/views/main.rs index 49006ce..7a40e89 100644 --- a/src/views/main.rs +++ b/src/views/main.rs @@ -6,17 +6,17 @@ use crate::i18n::Attr; use crate::receipt::Receipt; use crate::theme::{Button, Color, Icon, InfoBox, InfoBoxLevel, InfoBoxType}; use crate::views::AppView; -use eframe::egui::{self, Image}; +use eframe::egui; use humansize::{make_format, DECIMAL}; use std::path::Path; pub fn display(app: &mut ChecksumApp, ui: &mut egui::Ui) { let spacing = ui.spacing_mut(); app.default_padding = spacing.button_padding; - spacing.button_padding = egui::vec2(super::UI_BTN_PADDING_H, super::UI_BTN_PADDING_V); + spacing.button_padding = egui::vec2(crate::UI_BTN_PADDING_H, crate::UI_BTN_PADDING_V); add_header(app, ui); - ui.add_space(super::UI_MARGIN_LARGE); + ui.add_space(crate::UI_MARGIN_MEDIUM); add_file_selection(app, ui); add_messages(app, ui); add_loading(app, ui); @@ -63,10 +63,6 @@ fn build_file_list(app: &mut ChecksumApp, path: &Path) { } fn add_header(app: &mut ChecksumApp, ui: &mut egui::Ui) { - let (logo_name, logo_bytes) = app.theme.get_logo_bytes(); - ui.add(Image::from_bytes(logo_name, logo_bytes).fit_to_original_size(1.0)); - ui.add_space(super::UI_MARGIN_LARGE); - ui.horizontal(|ui| { ui.label(app.i18n.msg("label_nb_files_start")); let mut nb_str = app.nb_start.to_string(); @@ -79,7 +75,7 @@ fn add_header(app: &mut ChecksumApp, ui: &mut egui::Ui) { } }); - ui.add_space(super::UI_EXTRA_SPACE); + ui.add_space(crate::UI_MARGIN_SMALL); ui.horizontal(|ui| { // Button: select dir @@ -140,9 +136,9 @@ fn add_file_selection(app: &mut ChecksumApp, ui: &mut egui::Ui) { let p = fl.to_string(); ui.visuals_mut().override_text_color = Some(Color::FileSelection.get(app.theme)); egui::Frame::none() - .inner_margin(egui::Margin::from(crate::theme::LARGE_PADDING)) - .outer_margin(egui::Margin::from(0.0)) - .rounding(crate::theme::MAIN_ROUNDING) + .inner_margin(crate::UI_MARGIN_SMALL) + .outer_margin(crate::UI_MARGIN_NONE) + .rounding(crate::MAIN_ROUNDING) .fill(Color::FileSelectionBackground.get(app.theme)) .show(ui, |ui| { ui.horizontal(|ui| { @@ -162,16 +158,16 @@ fn add_file_selection(app: &mut ChecksumApp, ui: &mut egui::Ui) { } }); if app.file_list.is_some() && app.receipt.is_some() { - ui.add_space(super::UI_EXTRA_SPACE); + ui.add_space(crate::UI_MARGIN_SMALL); } ui.horizontal(|ui| { if let Some(e) = &app.receipt { let e = e.to_string(); ui.visuals_mut().override_text_color = Some(Color::FileSelection.get(app.theme)); egui::Frame::none() - .inner_margin(egui::Margin::from(crate::theme::LARGE_PADDING)) - .outer_margin(egui::Margin::from(0.0)) - .rounding(crate::theme::MAIN_ROUNDING) + .inner_margin(crate::UI_MARGIN_SMALL) + .outer_margin(crate::UI_MARGIN_NONE) + .rounding(crate::MAIN_ROUNDING) .fill(Color::FileSelectionBackground.get(app.theme)) .show(ui, |ui| { ui.horizontal(|ui| { @@ -191,77 +187,72 @@ fn add_file_selection(app: &mut ChecksumApp, ui: &mut egui::Ui) { } fn add_messages(app: &mut ChecksumApp, ui: &mut egui::Ui) { - egui::ScrollArea::vertical().show(ui, |ui| { - if let Some(p) = &app.file_list { - if p.has_content_file() { - ui.add_space(super::UI_EXTRA_SPACE); - InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Info).render_dyn( + if let Some(p) = &app.file_list { + if p.has_content_file() { + ui.add_space(crate::UI_MARGIN_SMALL); + InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Info).render_dyn(ui, |ui| { + ui.label(app.i18n.fmt( + "msg_info_has_ctn_file", + &[("file_name", Attr::String(app.content_file_name.clone()))], + )); + }); + } else { + let nb_files = p.get_nb_files(); + if nb_files >= app.clipboard_threshold { + ui.add_space(crate::UI_MARGIN_SMALL); + InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Warning).render_text( ui, - |ui| { - ui.label(app.i18n.fmt( - "msg_info_has_ctn_file", - &[("file_name", Attr::String(app.content_file_name.clone()))], - )); - }, + app.i18n + .fmt("msg_info_nb_files", &[("nb", Attr::Usize(nb_files))]), ); - } else { - let nb_files = p.get_nb_files(); - if nb_files >= app.clipboard_threshold { - ui.add_space(super::UI_EXTRA_SPACE); - InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Warning).render_text( - ui, - app.i18n - .fmt("msg_info_nb_files", &[("nb", Attr::Usize(nb_files))]), - ); - } } } - if let Some(msg) = &app.info_msg { - ui.add_space(super::UI_EXTRA_SPACE); - InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Info).render_text(ui, msg); - } - if let Some(msg) = &app.success_msg { - ui.add_space(super::UI_EXTRA_SPACE); - InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Success).render_text(ui, msg); - } - if let Some(msg) = &app.error_msg { - ui.add_space(super::UI_EXTRA_SPACE); - InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Warning).render_text(ui, msg); - } - if let Some(p) = &app.file_list { - if app.enable_duplicate_file_warning { - for fl in p.iter_duplicate_hashes() { - let mut msg = app.i18n.msg("msg_info_duplicate_hash"); - for f in fl { - msg += &format!("\n - {}", f.get_path().display()); - } - ui.add_space(super::UI_EXTRA_SPACE); - InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Warning) - .render_text(ui, &msg); + } + if let Some(msg) = &app.info_msg { + ui.add_space(crate::UI_MARGIN_SMALL); + InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Info).render_text(ui, msg); + } + if let Some(msg) = &app.success_msg { + ui.add_space(crate::UI_MARGIN_SMALL); + InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Success).render_text(ui, msg); + } + if let Some(msg) = &app.error_msg { + ui.add_space(crate::UI_MARGIN_SMALL); + InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Warning).render_text(ui, msg); + } + if let Some(p) = &app.file_list { + if app.enable_duplicate_file_warning { + for fl in p.iter_duplicate_hashes() { + let mut msg = app.i18n.msg("msg_info_duplicate_hash"); + for f in fl { + msg += &format!("\n - {}", f.get_path().display()); } + ui.add_space(crate::UI_MARGIN_SMALL); + InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Warning) + .render_text(ui, &msg); } - if app.enable_empty_file_warning { - for f in p.iter_empty_files() { - ui.add_space(super::UI_EXTRA_SPACE); - InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Warning).render_text( - ui, - app.i18n.fmt( - "msg_info_empty_file", - &[( - "file_name", - Attr::String(f.get_path().display().to_string()), - )], - ), - ); - } + } + if app.enable_empty_file_warning { + for f in p.iter_empty_files() { + ui.add_space(crate::UI_MARGIN_SMALL); + InfoBox::new(app.theme, InfoBoxType::Full, InfoBoxLevel::Warning).render_text( + ui, + app.i18n.fmt( + "msg_info_empty_file", + &[( + "file_name", + Attr::String(f.get_path().display().to_string()), + )], + ), + ); } } - }); + } } fn add_loading(app: &mut ChecksumApp, ui: &mut egui::Ui) { if let Some(flb) = &mut app.file_list_builder { - ui.add_space(super::UI_EXTRA_SPACE); + ui.add_space(crate::UI_MARGIN_SMALL); if let Some(af) = flb.ask_for() { ui.horizontal(|ui| { ui.add(egui::Spinner::new()); @@ -347,7 +338,7 @@ fn add_loading(app: &mut ChecksumApp, ui: &mut egui::Ui) { } fn add_action_buttons(app: &mut ChecksumApp, ui: &mut egui::Ui) { - ui.add_space(super::UI_MARGIN_LARGE); + ui.add_space(crate::UI_MARGIN_MEDIUM); ui.horizontal(|ui| { if app.file_hasher.is_none() { if let Some(p) = &mut app.file_list { @@ -430,7 +421,7 @@ fn add_action_buttons(app: &mut ChecksumApp, ui: &mut egui::Ui) { fn add_progress_bar(app: &mut ChecksumApp, ui: &mut egui::Ui) { if let Some(hr) = &app.file_hasher { - ui.add_space(super::UI_EXTRA_SPACE); + ui.add_space(crate::UI_MARGIN_SMALL); let progress_bar = egui::ProgressBar::new(hr.get_progress()) .show_percentage() .animate(true);