diff --git a/src/ui/activities/auth/view.rs b/src/ui/activities/auth/view.rs index e8efed9..0f8c638 100644 --- a/src/ui/activities/auth/view.rs +++ b/src/ui/activities/auth/view.rs @@ -6,7 +6,7 @@ use super::{components, AuthActivity, Context, FileTransferProtocol, Id, InputMask}; use crate::filetransfer::params::{AwsS3Params, GenericProtocolParams, ProtocolParams}; use crate::filetransfer::FileTransferParams; -use crate::utils::ui::draw_area_in; +use crate::utils::ui::{Popup, Size}; use std::path::PathBuf; use std::str::FromStr; @@ -193,43 +193,43 @@ impl AuthActivity { self.app.view(&Id::RecentsList, f, bookmark_chunks[1]); // Popups if self.app.mounted(&Id::ErrorPopup) { - let popup = draw_area_in(f.size(), 50, 10); + let popup = Popup(Size::Percentage(50), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::ErrorPopup, f, popup); } else if self.app.mounted(&Id::InfoPopup) { - let popup = draw_area_in(f.size(), 50, 10); + let popup = Popup(Size::Percentage(50), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::InfoPopup, f, popup); } else if self.app.mounted(&Id::WaitPopup) { - let popup = draw_area_in(f.size(), 50, 10); + let popup = Popup(Size::Percentage(50), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::WaitPopup, f, popup); } else if self.app.mounted(&Id::WindowSizeError) { - let popup = draw_area_in(f.size(), 80, 20); + let popup = Popup(Size::Percentage(80), Size::Percentage(20)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::WindowSizeError, f, popup); } else if self.app.mounted(&Id::QuitPopup) { // make popup - let popup = draw_area_in(f.size(), 30, 10); + let popup = Popup(Size::Percentage(30), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); self.app.view(&Id::QuitPopup, f, popup); } else if self.app.mounted(&Id::DeleteBookmarkPopup) { // make popup - let popup = draw_area_in(f.size(), 30, 10); + let popup = Popup(Size::Percentage(30), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); self.app.view(&Id::DeleteBookmarkPopup, f, popup); } else if self.app.mounted(&Id::DeleteRecentPopup) { // make popup - let popup = draw_area_in(f.size(), 30, 10); + let popup = Popup(Size::Percentage(30), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); self.app.view(&Id::DeleteRecentPopup, f, popup); } else if self.app.mounted(&Id::NewVersionChangelog) { // make popup - let popup = draw_area_in(f.size(), 90, 85); + let popup = Popup(Size::Percentage(90), Size::Percentage(85)).draw_in(f.size()); f.render_widget(Clear, popup); let popup_chunks = Layout::default() .direction(Direction::Vertical) @@ -245,12 +245,12 @@ impl AuthActivity { self.app.view(&Id::InstallUpdatePopup, f, popup_chunks[1]); } else if self.app.mounted(&Id::Keybindings) { // make popup - let popup = draw_area_in(f.size(), 50, 70); + let popup = Popup(Size::Percentage(50), Size::Percentage(70)).draw_in(f.size()); f.render_widget(Clear, popup); self.app.view(&Id::Keybindings, f, popup); } else if self.app.mounted(&Id::BookmarkSavePassword) { // make popup - let popup = draw_area_in(f.size(), 20, 20); + let popup = Popup(Size::Percentage(20), Size::Percentage(20)).draw_in(f.size()); f.render_widget(Clear, popup); let popup_chunks = Layout::default() .direction(Direction::Vertical) diff --git a/src/ui/activities/filetransfer/view.rs b/src/ui/activities/filetransfer/view.rs index 9be0e07..9a3b282 100644 --- a/src/ui/activities/filetransfer/view.rs +++ b/src/ui/activities/filetransfer/view.rs @@ -8,7 +8,7 @@ use super::{ components, Context, FileTransferActivity, Id, }; use crate::explorer::FileSorting; -use crate::utils::ui::draw_area_in; +use crate::utils::ui::{Popup, Size}; // Ext use remotefs::fs::File; use tuirealm::event::{Key, KeyEvent, KeyModifiers}; @@ -155,62 +155,62 @@ impl FileTransferActivity { self.app.view(&Id::StatusBarRemote, f, status_bar_chunks[1]); // @! Draw popups if self.app.mounted(&Id::CopyPopup) { - let popup = draw_area_in(f.size(), 40, 10); + let popup = Popup(Size::Percentage(40), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::CopyPopup, f, popup); } else if self.app.mounted(&Id::FindPopup) { - let popup = draw_area_in(f.size(), 40, 10); + let popup = Popup(Size::Percentage(40), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::FindPopup, f, popup); } else if self.app.mounted(&Id::GotoPopup) { - let popup = draw_area_in(f.size(), 40, 10); + let popup = Popup(Size::Percentage(40), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::GotoPopup, f, popup); } else if self.app.mounted(&Id::MkdirPopup) { - let popup = draw_area_in(f.size(), 40, 10); + let popup = Popup(Size::Percentage(40), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::MkdirPopup, f, popup); } else if self.app.mounted(&Id::NewfilePopup) { - let popup = draw_area_in(f.size(), 40, 10); + let popup = Popup(Size::Percentage(40), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::NewfilePopup, f, popup); } else if self.app.mounted(&Id::OpenWithPopup) { - let popup = draw_area_in(f.size(), 40, 10); + let popup = Popup(Size::Percentage(40), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::OpenWithPopup, f, popup); } else if self.app.mounted(&Id::RenamePopup) { - let popup = draw_area_in(f.size(), 40, 10); + let popup = Popup(Size::Percentage(40), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::RenamePopup, f, popup); } else if self.app.mounted(&Id::SaveAsPopup) { - let popup = draw_area_in(f.size(), 40, 10); + let popup = Popup(Size::Percentage(40), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::SaveAsPopup, f, popup); } else if self.app.mounted(&Id::SymlinkPopup) { - let popup = draw_area_in(f.size(), 50, 10); + let popup = Popup(Size::Percentage(50), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::SymlinkPopup, f, popup); } else if self.app.mounted(&Id::ExecPopup) { - let popup = draw_area_in(f.size(), 40, 10); + let popup = Popup(Size::Percentage(40), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::ExecPopup, f, popup); } else if self.app.mounted(&Id::FileInfoPopup) { - let popup = draw_area_in(f.size(), 50, 50); + let popup = Popup(Size::Percentage(50), Size::Percentage(50)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::FileInfoPopup, f, popup); } else if self.app.mounted(&Id::ProgressBarPartial) { - let popup = draw_area_in(f.size(), 50, 20); + let popup = Popup(Size::Percentage(50), Size::Percentage(20)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup let popup_chunks = Layout::default() @@ -226,14 +226,14 @@ impl FileTransferActivity { self.app.view(&Id::ProgressBarFull, f, popup_chunks[0]); self.app.view(&Id::ProgressBarPartial, f, popup_chunks[1]); } else if self.app.mounted(&Id::DeletePopup) { - let popup = draw_area_in(f.size(), 30, 10); + let popup = Popup(Size::Percentage(30), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::DeletePopup, f, popup); } else if self.app.mounted(&Id::ReplacePopup) { // NOTE: handle extended / normal modes if self.is_radio_replace_extended() { - let popup = draw_area_in(f.size(), 50, 50); + let popup = Popup(Size::Percentage(50), Size::Percentage(50)).draw_in(f.size()); f.render_widget(Clear, popup); let popup_chunks = Layout::default() .direction(Direction::Vertical) @@ -249,66 +249,66 @@ impl FileTransferActivity { .view(&Id::ReplacingFilesListPopup, f, popup_chunks[0]); self.app.view(&Id::ReplacePopup, f, popup_chunks[1]); } else { - let popup = draw_area_in(f.size(), 50, 10); + let popup = Popup(Size::Percentage(50), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::ReplacePopup, f, popup); } } else if self.app.mounted(&Id::DisconnectPopup) { - let popup = draw_area_in(f.size(), 30, 10); + let popup = Popup(Size::Percentage(30), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::DisconnectPopup, f, popup); } else if self.app.mounted(&Id::QuitPopup) { - let popup = draw_area_in(f.size(), 30, 10); + let popup = Popup(Size::Percentage(30), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::QuitPopup, f, popup); } else if self.app.mounted(&Id::WatchedPathsList) { - let popup = draw_area_in(f.size(), 60, 50); + let popup = Popup(Size::Percentage(60), Size::Percentage(50)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::WatchedPathsList, f, popup); } else if self.app.mounted(&Id::WatcherPopup) { - let popup = draw_area_in(f.size(), 60, 10); + let popup = Popup(Size::Percentage(60), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::WatcherPopup, f, popup); } else if self.app.mounted(&Id::SortingPopup) { - let popup = draw_area_in(f.size(), 50, 10); + let popup = Popup(Size::Percentage(50), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::SortingPopup, f, popup); } else if self.app.mounted(&Id::ErrorPopup) { - let popup = draw_area_in( - f.size(), - 50, + let popup = Popup( + Size::Percentage(50), self.calc_popup_height(Id::ErrorPopup, f.size().width, f.size().height), - ); + ) + .draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::ErrorPopup, f, popup); } else if self.app.mounted(&Id::FatalPopup) { - let popup = draw_area_in( - f.size(), - 50, + let popup = Popup( + Size::Percentage(50), self.calc_popup_height(Id::FatalPopup, f.size().width, f.size().height), - ); + ) + .draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::FatalPopup, f, popup); } else if self.app.mounted(&Id::WaitPopup) { - let popup = draw_area_in(f.size(), 50, 10); + let popup = Popup(Size::Percentage(50), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::WaitPopup, f, popup); } else if self.app.mounted(&Id::SyncBrowsingMkdirPopup) { - let popup = draw_area_in(f.size(), 60, 10); + let popup = Popup(Size::Percentage(60), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::SyncBrowsingMkdirPopup, f, popup); } else if self.app.mounted(&Id::KeybindingsPopup) { - let popup = draw_area_in(f.size(), 50, 80); + let popup = Popup(Size::Percentage(50), Size::Percentage(80)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::KeybindingsPopup, f, popup); @@ -890,7 +890,7 @@ impl FileTransferActivity { /// Given the id of the component to display and the width and height of the total area, /// returns the height in percentage to the entire area height, that the popup should have - fn calc_popup_height(&self, id: Id, width: u16, height: u16) -> u16 { + fn calc_popup_height(&self, id: Id, width: u16, height: u16) -> Size { // Get current text width let text_width = self .app @@ -914,7 +914,7 @@ impl FileTransferActivity { // Get amount of required rows NOTE: + 2 because of margins let display_rows = ((text_width as f64) / (row_width as f64)).ceil() as u16 + 2; // Return height (row_height_p * display_rows) - display_rows * row_height_p + Size::Percentage(display_rows * row_height_p) } // -- global listener diff --git a/src/ui/activities/setup/view/mod.rs b/src/ui/activities/setup/view/mod.rs index 4204dc4..d866153 100644 --- a/src/ui/activities/setup/view/mod.rs +++ b/src/ui/activities/setup/view/mod.rs @@ -8,7 +8,7 @@ pub mod ssh_keys; pub mod theme; use super::*; -use crate::utils::ui::draw_area_in; +use crate::utils::ui::{Popup, Size}; pub use setup::*; pub use ssh_keys::*; pub use theme::*; @@ -117,23 +117,23 @@ impl SetupActivity { pub(super) fn view_popups(&mut self, f: &mut Frame) { if self.app.mounted(&Id::Common(IdCommon::ErrorPopup)) { - let popup = draw_area_in(f.size(), 50, 10); + let popup = Popup(Size::Percentage(50), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); // make popup self.app.view(&Id::Common(IdCommon::ErrorPopup), f, popup); } else if self.app.mounted(&Id::Common(IdCommon::QuitPopup)) { // make popup - let popup = draw_area_in(f.size(), 40, 10); + let popup = Popup(Size::Percentage(40), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); self.app.view(&Id::Common(IdCommon::QuitPopup), f, popup); } else if self.app.mounted(&Id::Common(IdCommon::Keybindings)) { // make popup - let popup = draw_area_in(f.size(), 50, 70); + let popup = Popup(Size::Percentage(50), Size::Percentage(70)).draw_in(f.size()); f.render_widget(Clear, popup); self.app.view(&Id::Common(IdCommon::Keybindings), f, popup); } else if self.app.mounted(&Id::Common(IdCommon::SavePopup)) { // make popup - let popup = draw_area_in(f.size(), 30, 10); + let popup = Popup(Size::Percentage(30), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); self.app.view(&Id::Common(IdCommon::SavePopup), f, popup); } diff --git a/src/ui/activities/setup/view/ssh_keys.rs b/src/ui/activities/setup/view/ssh_keys.rs index 59d87d0..33b1e44 100644 --- a/src/ui/activities/setup/view/ssh_keys.rs +++ b/src/ui/activities/setup/view/ssh_keys.rs @@ -5,7 +5,7 @@ // Locals use super::{components, Context, Id, IdCommon, IdSsh, SetupActivity, ViewLayout}; -use crate::utils::ui::draw_area_in; +use crate::utils::ui::{Popup, Size}; // Ext use tuirealm::tui::layout::{Constraint, Direction, Layout}; @@ -45,11 +45,11 @@ impl SetupActivity { // Popups self.view_popups(f); if self.app.mounted(&Id::Ssh(IdSsh::DelSshKeyPopup)) { - let popup = draw_area_in(f.size(), 30, 10); + let popup = Popup(Size::Percentage(30), Size::Unit(3)).draw_in(f.size()); f.render_widget(Clear, popup); self.app.view(&Id::Ssh(IdSsh::DelSshKeyPopup), f, popup); } else if self.app.mounted(&Id::Ssh(IdSsh::SshHost)) { - let popup = draw_area_in(f.size(), 50, 20); + let popup = Popup(Size::Percentage(50), Size::Percentage(20)).draw_in(f.size()); f.render_widget(Clear, popup); let popup_chunks = Layout::default() .direction(Direction::Vertical) diff --git a/src/utils/ui.rs b/src/utils/ui.rs index 9f41c9d..6e69d6c 100644 --- a/src/utils/ui.rs +++ b/src/utils/ui.rs @@ -4,32 +4,54 @@ use tuirealm::tui::layout::{Constraint, Direction, Layout, Rect}; -/// ### draw_area_in -/// -/// Draw an area (WxH / 3) in the middle of the parent area -pub fn draw_area_in(parent: Rect, width: u16, height: u16) -> Rect { - let new_area = Layout::default() - .direction(Direction::Vertical) - .constraints( - [ - Constraint::Percentage((100 - height) / 2), - Constraint::Percentage(height), - Constraint::Percentage((100 - height) / 2), - ] - .as_ref(), - ) - .split(parent); - Layout::default() - .direction(Direction::Horizontal) - .constraints( - [ - Constraint::Percentage((100 - width) / 2), - Constraint::Percentage(width), - Constraint::Percentage((100 - width) / 2), - ] - .as_ref(), - ) - .split(new_area[1])[1] +/// Size type for UI renders +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum Size { + Percentage(u16), + Unit(u16), +} + +/// Ui popup dialog (w x h) +pub struct Popup(pub Size, pub Size); + +impl Popup { + /// Draw popup in provided area + pub fn draw_in(&self, parent: Rect) -> Rect { + let new_area = Layout::default() + .direction(Direction::Vertical) + .constraints(self.height(&parent).as_ref()) + .split(parent); + Layout::default() + .direction(Direction::Horizontal) + .constraints(self.width(&parent).as_ref()) + .split(new_area[1])[1] + } + + fn height(&self, parent: &Rect) -> [Constraint; 3] { + Self::constraints(parent.height, self.1) + } + + fn width(&self, parent: &Rect) -> [Constraint; 3] { + Self::constraints(parent.width, self.0) + } + + fn constraints(area_size: u16, popup_size: Size) -> [Constraint; 3] { + match popup_size { + Size::Percentage(popup_size) => [ + Constraint::Percentage((100 - popup_size) / 2), + Constraint::Percentage(popup_size), + Constraint::Percentage((100 - popup_size) / 2), + ], + Size::Unit(popup_size) => { + let margin = (area_size - popup_size) / 2; + [ + Constraint::Length(margin), + Constraint::Length(popup_size), + Constraint::Length(margin), + ] + } + } + } } #[cfg(test)] @@ -42,7 +64,7 @@ mod tests { #[test] fn test_utils_ui_draw_area_in() { let area: Rect = Rect::new(0, 0, 1024, 512); - let child: Rect = draw_area_in(area, 75, 30); + let child: Rect = Popup(Size::Percentage(75), Size::Percentage(30)).draw_in(area); assert_eq!(child.x, 43); assert_eq!(child.y, 63); assert_eq!(child.width, 271);