ui: root to content, macos related window fixes

This commit is contained in:
ardocrat 2024-07-02 23:52:25 +03:00
parent 84d71e371d
commit 03a3dc097a
20 changed files with 203 additions and 214 deletions

View file

@ -16,12 +16,13 @@ use std::sync::atomic::{AtomicBool, Ordering};
use lazy_static::lazy_static;
use egui::{Align, Context, CursorIcon, Layout, Modifiers, Rect, ResizeDirection, Rounding, Stroke, ViewportCommand};
use egui::epaint::{RectShape};
use egui::os::OperatingSystem;
use crate::{AppConfig, built_info};
use crate::gui::Colors;
use crate::gui::icons::{ARROWS_IN, ARROWS_OUT, CARET_DOWN, MOON, SUN, X};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Root, TitlePanel, View};
use crate::gui::views::{Content, TitlePanel, View};
lazy_static! {
/// State to check if platform Back button was pressed.
@ -34,7 +35,7 @@ pub struct App<Platform> {
pub(crate) platform: Platform,
/// Main ui content.
root: Root,
content: Content,
/// Last window resize direction.
resize_direction: Option<ResizeDirection>
@ -42,16 +43,16 @@ pub struct App<Platform> {
impl<Platform: PlatformCallbacks> App<Platform> {
pub fn new(platform: Platform) -> Self {
Self { platform, root: Root::default(), resize_direction: None }
Self { platform, content: Content::default(), resize_direction: None }
}
/// Draw application content.
pub fn ui(&mut self, ctx: &Context) {
// Handle Esc keyboard key event and platform Back button key event.
let back_button_pressed = BACK_BUTTON_PRESSED.load(Ordering::Relaxed);
if ctx.input_mut(|i| i.consume_key(Modifiers::NONE, egui::Key::Escape)) || back_button_pressed {
self.root.on_back();
if back_button_pressed {
let back_pressed = BACK_BUTTON_PRESSED.load(Ordering::Relaxed);
if ctx.input_mut(|i| i.consume_key(Modifiers::NONE, egui::Key::Escape)) || back_pressed {
self.content.on_back();
if back_pressed {
BACK_BUTTON_PRESSED.store(false, Ordering::Relaxed);
}
// Request repaint to update previous content.
@ -60,9 +61,9 @@ impl<Platform: PlatformCallbacks> App<Platform> {
// Handle Close event (on desktop).
if ctx.input(|i| i.viewport().close_requested()) {
if !self.root.exit_allowed {
if !self.content.exit_allowed {
ctx.send_viewport_cmd(ViewportCommand::CancelClose);
Root::show_exit_modal();
Content::show_exit_modal();
} else {
ctx.input(|i| {
if let Some(rect) = i.viewport().inner_rect {
@ -81,10 +82,15 @@ impl<Platform: PlatformCallbacks> App<Platform> {
..Default::default()
})
.show(ctx, |ui| {
if View::is_desktop() {
let is_mac_os = OperatingSystem::from_target_os() == OperatingSystem::Mac;
if View::is_desktop() && !is_mac_os {
self.desktop_window_ui(ui);
} else {
self.root.ui(ui, &self.platform);
if is_mac_os {
self.window_title_ui(ui);
ui.add_space(-1.0);
}
self.content.ui(ui, &self.platform);
}
});
}
@ -98,13 +104,13 @@ impl<Platform: PlatformCallbacks> App<Platform> {
let title_stroke_rect = {
let mut rect = ui.max_rect();
if !is_fullscreen {
rect = rect.shrink(Root::WINDOW_FRAME_MARGIN);
rect = rect.shrink(Content::WINDOW_FRAME_MARGIN);
}
rect.max.y = if !is_fullscreen {
Root::WINDOW_FRAME_MARGIN
Content::WINDOW_FRAME_MARGIN
} else {
0.0
} + Root::WINDOW_TITLE_HEIGHT + TitlePanel::DEFAULT_HEIGHT + 0.5;
} + Content::WINDOW_TITLE_HEIGHT + TitlePanel::DEFAULT_HEIGHT + 0.5;
rect
};
let title_stroke = RectShape {
@ -130,9 +136,9 @@ impl<Platform: PlatformCallbacks> App<Platform> {
let content_stroke_rect = {
let mut rect = ui.max_rect();
if !is_fullscreen {
rect = rect.shrink(Root::WINDOW_FRAME_MARGIN);
rect = rect.shrink(Content::WINDOW_FRAME_MARGIN);
}
let top = Root::WINDOW_TITLE_HEIGHT + TitlePanel::DEFAULT_HEIGHT + 0.5;
let top = Content::WINDOW_TITLE_HEIGHT + TitlePanel::DEFAULT_HEIGHT + 0.5;
rect.min += egui::vec2(0.0, top);
rect
};
@ -154,9 +160,10 @@ impl<Platform: PlatformCallbacks> App<Platform> {
// Draw window content.
let mut content_rect = ui.max_rect();
if !is_fullscreen {
content_rect = content_rect.shrink(Root::WINDOW_FRAME_MARGIN);
content_rect = content_rect.shrink(Content::WINDOW_FRAME_MARGIN);
}
ui.allocate_ui_at_rect(content_rect, |ui| {
self.window_title_ui(ui);
self.window_content(ui);
});
@ -175,11 +182,23 @@ impl<Platform: PlatformCallbacks> App<Platform> {
/// Draw window content for desktop.
fn window_content(&mut self, ui: &mut egui::Ui) {
let content_rect = {
let mut rect = ui.max_rect();
rect.min.y += Content::WINDOW_TITLE_HEIGHT;
rect
};
// Draw main content.
let mut content_ui = ui.child_ui(content_rect, *ui.layout(), None);
self.content.ui(&mut content_ui, &self.platform);
}
/// Draw custom window title content.
fn window_title_ui(&self, ui: &mut egui::Ui) {
let content_rect = ui.max_rect();
let window_title_rect = {
let title_rect = {
let mut rect = content_rect;
rect.max.y = rect.min.y + Root::WINDOW_TITLE_HEIGHT;
rect.max.y = rect.min.y + Content::WINDOW_TITLE_HEIGHT;
rect
};
@ -188,7 +207,7 @@ impl<Platform: PlatformCallbacks> App<Platform> {
});
let window_title_bg = RectShape {
rect: window_title_rect,
rect: title_rect,
rounding: if is_fullscreen {
Rounding::ZERO
} else {
@ -205,33 +224,15 @@ impl<Platform: PlatformCallbacks> App<Platform> {
fill_texture_id: Default::default(),
uv: Rect::ZERO
};
// Draw title background.
ui.painter().add(window_title_bg);
// Draw window title.
self.window_title_ui(ui, window_title_rect);
let content_rect = {
let mut rect = content_rect;
rect.min.y = window_title_rect.max.y;
rect
};
// Draw main content.
let mut content_ui = ui.child_ui(content_rect, *ui.layout(), None);
self.root.ui(&mut content_ui, &self.platform);
}
/// Draw custom window title content.
fn window_title_ui(&self, ui: &mut egui::Ui, title_rect: Rect) {
let is_fullscreen = ui.ctx().input(|i| {
i.viewport().fullscreen.unwrap_or(false)
});
let painter = ui.painter();
let interact_rect = {
let mut rect = title_rect;
if !is_fullscreen {
rect.min.y += Root::WINDOW_FRAME_MARGIN;
rect.min.y += Content::WINDOW_FRAME_MARGIN;
}
rect
};
@ -243,15 +244,15 @@ impl<Platform: PlatformCallbacks> App<Platform> {
// Paint the title.
let dual_wallets_panel =
ui.available_width() >= (Root::SIDE_PANEL_WIDTH * 3.0) + View::get_right_inset();
let wallet_panel_opened = self.root.wallets.wallet_panel_opened();
ui.available_width() >= (Content::SIDE_PANEL_WIDTH * 3.0) + View::get_right_inset();
let wallet_panel_opened = self.content.wallets.wallet_panel_opened();
let hide_app_name = if dual_wallets_panel {
!wallet_panel_opened || (AppConfig::show_wallets_at_dual_panel() &&
self.root.wallets.showing_wallet() && !self.root.wallets.creating_wallet())
} else if Root::is_dual_panel_mode(ui) {
self.content.wallets.showing_wallet() && !self.content.wallets.creating_wallet())
} else if Content::is_dual_panel_mode(ui) {
!wallet_panel_opened
} else {
!Root::is_network_panel_open() && !wallet_panel_opened
!Content::is_network_panel_open() && !wallet_panel_opened
};
let title_text = if hide_app_name {
"".to_string()
@ -279,7 +280,7 @@ impl<Platform: PlatformCallbacks> App<Platform> {
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
// Draw button to close window.
View::title_button_small(ui, X, |_| {
Root::show_exit_modal();
Content::show_exit_modal();
});
// Draw fullscreen button.
@ -323,47 +324,47 @@ impl<Platform: PlatformCallbacks> App<Platform> {
// Setup area id, cursor and area rect based on direction.
let (id, cursor, rect) = match direction {
ResizeDirection::North => ("n", CursorIcon::ResizeNorth, {
rect.min.x += Root::WINDOW_FRAME_MARGIN * 2.0;
rect.max.y = rect.min.y + Root::WINDOW_FRAME_MARGIN;
rect.max.x -= Root::WINDOW_FRAME_MARGIN * 2.0;
rect.min.x += Content::WINDOW_FRAME_MARGIN * 2.0;
rect.max.y = rect.min.y + Content::WINDOW_FRAME_MARGIN;
rect.max.x -= Content::WINDOW_FRAME_MARGIN * 2.0;
rect
}),
ResizeDirection::East => ("e", CursorIcon::ResizeEast, {
rect.min.y += Root::WINDOW_FRAME_MARGIN * 2.0;
rect.min.x = rect.max.x - Root::WINDOW_FRAME_MARGIN;
rect.max.y -= Root::WINDOW_FRAME_MARGIN * 2.0;
rect.min.y += Content::WINDOW_FRAME_MARGIN * 2.0;
rect.min.x = rect.max.x - Content::WINDOW_FRAME_MARGIN;
rect.max.y -= Content::WINDOW_FRAME_MARGIN * 2.0;
rect
}),
ResizeDirection::South => ("s", CursorIcon::ResizeSouth, {
rect.min.x += Root::WINDOW_FRAME_MARGIN * 2.0;
rect.min.y = rect.max.y - Root::WINDOW_FRAME_MARGIN;
rect.max.x -= Root::WINDOW_FRAME_MARGIN * 2.0;
rect.min.x += Content::WINDOW_FRAME_MARGIN * 2.0;
rect.min.y = rect.max.y - Content::WINDOW_FRAME_MARGIN;
rect.max.x -= Content::WINDOW_FRAME_MARGIN * 2.0;
rect
}),
ResizeDirection::West => ("w", CursorIcon::ResizeWest, {
rect.min.y += Root::WINDOW_FRAME_MARGIN * 2.0;
rect.max.x = rect.min.x + Root::WINDOW_FRAME_MARGIN;
rect.max.y -= Root::WINDOW_FRAME_MARGIN * 2.0;
rect.min.y += Content::WINDOW_FRAME_MARGIN * 2.0;
rect.max.x = rect.min.x + Content::WINDOW_FRAME_MARGIN;
rect.max.y -= Content::WINDOW_FRAME_MARGIN * 2.0;
rect
}),
ResizeDirection::NorthWest => ("nw", CursorIcon::ResizeNorthWest, {
rect.max.y = rect.min.y + Root::WINDOW_FRAME_MARGIN * 2.0;
rect.max.x = rect.max.y + Root::WINDOW_FRAME_MARGIN * 2.0;
rect.max.y = rect.min.y + Content::WINDOW_FRAME_MARGIN * 2.0;
rect.max.x = rect.max.y + Content::WINDOW_FRAME_MARGIN * 2.0;
rect
}),
ResizeDirection::NorthEast => ("ne", CursorIcon::ResizeNorthEast, {
rect.min.x = rect.max.x - Root::WINDOW_FRAME_MARGIN * 2.0;
rect.max.y = Root::WINDOW_FRAME_MARGIN * 2.0;
rect.min.x = rect.max.x - Content::WINDOW_FRAME_MARGIN * 2.0;
rect.max.y = Content::WINDOW_FRAME_MARGIN * 2.0;
rect
}),
ResizeDirection::SouthEast => ("se", CursorIcon::ResizeSouthEast, {
rect.min.y = rect.max.y - Root::WINDOW_FRAME_MARGIN * 2.0;
rect.min.x = rect.max.x - Root::WINDOW_FRAME_MARGIN * 2.0;
rect.min.y = rect.max.y - Content::WINDOW_FRAME_MARGIN * 2.0;
rect.min.x = rect.max.x - Content::WINDOW_FRAME_MARGIN * 2.0;
rect
}),
ResizeDirection::SouthWest => ("sw", CursorIcon::ResizeSouthWest, {
rect.min.y = rect.max.y - Root::WINDOW_FRAME_MARGIN * 2.0;
rect.max.x = rect.min.x + Root::WINDOW_FRAME_MARGIN * 2.0;
rect.min.y = rect.max.y - Content::WINDOW_FRAME_MARGIN * 2.0;
rect.max.x = rect.min.x + Content::WINDOW_FRAME_MARGIN * 2.0;
rect
}),
};
@ -391,8 +392,17 @@ impl<Platform: PlatformCallbacks> eframe::App for App<Platform> {
}
fn clear_color(&self, _visuals: &egui::Visuals) -> [f32; 4] {
if View::is_desktop() {
let is_mac_os = OperatingSystem::from_target_os() == OperatingSystem::Mac;
if is_mac_os {
Colors::fill().to_normalized_gamma_f32()
} else {
egui::Rgba::TRANSPARENT.to_array()
}
} else {
Colors::fill().to_normalized_gamma_f32()
}
}
}
#[allow(dead_code)]

View file

@ -31,7 +31,7 @@ lazy_static! {
}
/// Contains main ui content, handles side panel state.
pub struct Root {
pub struct Content {
/// Side panel [`NetworkContent`] content.
network: NetworkContent,
/// Central panel [`WalletsContent`] content.
@ -49,7 +49,7 @@ pub struct Root {
allowed_modal_ids: Vec<&'static str>
}
impl Default for Root {
impl Default for Content {
fn default() -> Self {
// Exit from eframe only for non-mobile platforms.
let os = OperatingSystem::from_target_os();
@ -69,7 +69,7 @@ impl Default for Root {
}
}
impl ModalContainer for Root {
impl ModalContainer for Content {
fn modal_ids(&self) -> &Vec<&'static str> {
&self.allowed_modal_ids
}
@ -87,7 +87,7 @@ impl ModalContainer for Root {
}
}
impl Root {
impl Content {
/// Identifier for exit confirmation [`Modal`].
pub const EXIT_MODAL_ID: &'static str = "exit_confirmation_modal";
/// Identifier for wallet opening [`Modal`].
@ -153,7 +153,8 @@ impl Root {
let is_fullscreen = ui.ctx().input(|i| {
i.viewport().fullscreen.unwrap_or(false)
});
View::window_size(ui).0 - if View::is_desktop() && !is_fullscreen {
View::window_size(ui).0 - if View::is_desktop() && !is_fullscreen &&
OperatingSystem::from_target_os() != OperatingSystem::Mac {
Self::WINDOW_FRAME_MARGIN * 2.0
} else {
0.0

View file

@ -23,8 +23,8 @@ pub use title_panel::*;
mod modal;
pub use modal::*;
mod root;
pub use root::*;
mod content;
pub use content::*;
mod network;
pub use network::*;

View file

@ -18,9 +18,10 @@ use parking_lot::RwLock;
use std::sync::atomic::{AtomicBool, Ordering};
use egui::{Align2, Rect, RichText, Rounding, Stroke, Vec2};
use egui::epaint::{RectShape, Shadow};
use egui::os::OperatingSystem;
use crate::gui::Colors;
use crate::gui::views::{Root, View};
use crate::gui::views::{Content, View};
use crate::gui::views::types::{ModalPosition, ModalState};
lazy_static! {
@ -45,7 +46,7 @@ impl Modal {
/// Margin from [`Modal`] window at top/left/right.
const DEFAULT_MARGIN: f32 = 8.0;
/// Maximum width of the content.
const DEFAULT_WIDTH: f32 = Root::SIDE_PANEL_WIDTH - (2.0 * Self::DEFAULT_MARGIN);
const DEFAULT_WIDTH: f32 = Content::SIDE_PANEL_WIDTH - (2.0 * Self::DEFAULT_MARGIN);
/// Create closeable [`Modal`] with center position.
pub fn new(id: &'static str) -> Self {
@ -163,16 +164,17 @@ impl Modal {
let is_fullscreen = ctx.input(|i| {
i.viewport().fullscreen.unwrap_or(false)
});
let is_mac_os = OperatingSystem::from_target_os() == OperatingSystem::Mac;
let mut rect = ctx.screen_rect();
if View::is_desktop() {
if View::is_desktop() && !is_mac_os {
let margin = if !is_fullscreen {
Root::WINDOW_FRAME_MARGIN
Content::WINDOW_FRAME_MARGIN
} else {
0.0
};
rect = rect.shrink(margin - 0.5);
rect.min += egui::vec2(0.0, Root::WINDOW_TITLE_HEIGHT + 0.5);
rect.min += egui::vec2(0.0, Content::WINDOW_TITLE_HEIGHT + 0.5);
rect.max.x += 0.5;
}
egui::Window::new("modal_bg_window")
@ -231,16 +233,21 @@ impl Modal {
ModalPosition::CenterTop => Align2::CENTER_TOP,
ModalPosition::Center => Align2::CENTER_CENTER
};
let x_align = View::get_left_inset() - View::get_right_inset();
let y_align = View::get_top_inset() + Self::DEFAULT_MARGIN + if View::is_desktop() {
Root::WINDOW_TITLE_HEIGHT + if !is_fullscreen {
Root::WINDOW_FRAME_MARGIN
let is_mac_os = OperatingSystem::from_target_os() == OperatingSystem::Mac;
let extra_y = if View::is_desktop() && !is_mac_os {
Content::WINDOW_TITLE_HEIGHT + if !is_fullscreen {
Content::WINDOW_FRAME_MARGIN
} else {
0.0
}
} else {
0.0
};
let y_align = View::get_top_inset() + Self::DEFAULT_MARGIN + extra_y;
let offset = match self.position {
ModalPosition::CenterTop => Vec2::new(x_align, y_align),
ModalPosition::Center => Vec2::new(x_align, 0.0)

View file

@ -20,7 +20,7 @@ use crate::AppConfig;
use crate::gui::Colors;
use crate::gui::icons::{ARROWS_COUNTER_CLOCKWISE, BRIEFCASE, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE, POWER};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{ConnectionsContent, NetworkMetrics, NetworkMining, NetworkNode, NetworkSettings, Root, TitlePanel, View};
use crate::gui::views::{ConnectionsContent, NetworkMetrics, NetworkMining, NetworkNode, NetworkSettings, Content, TitlePanel, View};
use crate::gui::views::network::types::{NetworkTab, NetworkTabType};
use crate::gui::views::types::{TitleContentType, TitleType};
use crate::node::{Node, NodeError};
@ -46,7 +46,7 @@ impl Default for NetworkContent {
impl NetworkContent {
pub fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
let show_connections = AppConfig::show_connections_network_panel();
let dual_panel = Root::is_dual_panel_mode(ui);
let dual_panel = Content::is_dual_panel_mode(ui);
// Show title panel.
self.title_ui(ui, show_connections);
@ -68,7 +68,7 @@ impl NetworkContent {
})
.show_inside(ui, |ui| {
ui.vertical_centered(|ui| {
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
self.tabs_ui(ui);
});
});
@ -80,20 +80,6 @@ impl NetworkContent {
.resizable(false)
.exact_width(ui.available_width())
.frame(egui::Frame {
outer_margin: if !show_connections {
Margin {
left: 0.0,
right: if !dual_panel {
-0.5
} else {
0.0
},
top: 0.0,
bottom: 0.0,
}
} else {
Margin::ZERO
},
..Default::default()
})
.show_animated_inside(ui, !show_connections, |ui| {
@ -115,25 +101,6 @@ impl NetworkContent {
});
// Show connections content.
egui::CentralPanel::default()
.frame(egui::Frame {
outer_margin: if show_connections {
Margin {
left: 0.0,
right: if !dual_panel {
-0.5
} else {
0.0
},
top: 0.0,
bottom: 0.0,
}
} else {
Margin::ZERO
},
..Default::default()
})
.show_inside(ui, |ui| {
egui::CentralPanel::default()
.frame(egui::Frame {
stroke: View::item_stroke(),
@ -167,7 +134,7 @@ impl NetworkContent {
ui.add_space(1.0);
ui.vertical_centered(|ui| {
let max_width = if !dual_panel {
Root::SIDE_PANEL_WIDTH * 1.3
Content::SIDE_PANEL_WIDTH * 1.3
} else {
ui.available_width()
};
@ -177,7 +144,6 @@ impl NetworkContent {
});
});
});
});
// Redraw after delay.
if Node::is_running() {
@ -245,9 +211,9 @@ impl NetworkContent {
});
}
}, |ui| {
if !Root::is_dual_panel_mode(ui) {
if !Content::is_dual_panel_mode(ui) {
View::title_button_big(ui, BRIEFCASE, |_| {
Root::toggle_network_panel();
Content::toggle_network_panel();
});
}
}, ui);

View file

@ -19,7 +19,7 @@ use grin_servers::{DiffBlock, ServerStats};
use crate::gui::Colors;
use crate::gui::icons::{AT, COINS, CUBE_TRANSPARENT, HOURGLASS_LOW, HOURGLASS_MEDIUM, TIMER};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{NetworkContent, Root, View};
use crate::gui::views::{NetworkContent, Content, View};
use crate::gui::views::network::types::{NetworkTab, NetworkTabType};
use crate::node::Node;
@ -66,7 +66,7 @@ impl NetworkTab for NetworkMetrics {
ui.add_space(1.0);
ui.vertical_centered(|ui| {
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
let stats = server_stats.as_ref().unwrap();
// Show emission and difficulty info.
info_ui(ui, stats);

View file

@ -20,7 +20,7 @@ use grin_servers::WorkerStats;
use crate::gui::Colors;
use crate::gui::icons::{BARBELL, CLOCK_AFTERNOON, CPU, CUBE, FADERS, FOLDER_DASHED, FOLDER_SIMPLE_MINUS, FOLDER_SIMPLE_PLUS, HARD_DRIVES, PLUGS, PLUGS_CONNECTED, POLYGON};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{NetworkContent, Root, View};
use crate::gui::views::{NetworkContent, Content, View};
use crate::gui::views::network::setup::StratumSetup;
use crate::gui::views::network::types::{NetworkTab, NetworkTabType};
use crate::node::{Node, NodeConfig};
@ -82,7 +82,7 @@ impl NetworkTab for NetworkMining {
.show(ui, |ui| {
ui.add_space(1.0);
ui.vertical_centered(|ui| {
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
self.stratum_server_setup.ui(ui, cb);
});
});

View file

@ -19,7 +19,7 @@ use grin_servers::PeerStats;
use crate::gui::Colors;
use crate::gui::icons::{AT, CUBE, DEVICES, FLOW_ARROW, HANDSHAKE, PACKAGE, SHARE_NETWORK};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{NetworkContent, Root, View};
use crate::gui::views::{NetworkContent, Content, View};
use crate::gui::views::network::types::{NetworkTab, NetworkTabType};
use crate::node::{Node, NodeConfig};
@ -60,7 +60,7 @@ impl NetworkTab for NetworkNode {
.show(ui, |ui| {
ui.add_space(2.0);
ui.vertical_centered(|ui| {
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
// Show node stats content.
node_stats_ui(ui);
});

View file

@ -18,7 +18,7 @@ use egui::scroll_area::ScrollBarVisibility;
use crate::gui::Colors;
use crate::gui::icons::ARROW_COUNTER_CLOCKWISE;
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, Root, View};
use crate::gui::views::{Modal, Content, View};
use crate::gui::views::network::setup::{DandelionSetup, NodeSetup, P2PSetup, PoolSetup, StratumSetup};
use crate::gui::views::network::types::{NetworkTab, NetworkTabType};
use crate::gui::views::types::{ModalContainer, ModalPosition};
@ -91,7 +91,7 @@ impl NetworkTab for NetworkSettings {
.show(ui, |ui| {
ui.add_space(1.0);
ui.vertical_centered(|ui| {
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
// Draw node setup section.
self.node.ui(ui, cb);

View file

@ -16,7 +16,7 @@ use egui::{Margin, Id};
use egui_extras::{Size, Strip, StripBuilder};
use crate::gui::Colors;
use crate::gui::views::{Root, View};
use crate::gui::views::{Content, View};
use crate::gui::views::types::{TitleContentType, TitleType};
/// Title panel with left/right action buttons and text in the middle.
@ -66,7 +66,7 @@ impl TitlePanel {
StripBuilder::new(ui)
.size(Size::exact(Self::DEFAULT_HEIGHT))
.size(if dual_title {
Size::exact(Root::SIDE_PANEL_WIDTH - 2.0 * Self::DEFAULT_HEIGHT)
Size::exact(Content::SIDE_PANEL_WIDTH - 2.0 * Self::DEFAULT_HEIGHT)
} else {
Size::remainder()
})

View file

@ -20,7 +20,7 @@ use crate::AppConfig;
use crate::gui::Colors;
use crate::gui::icons::{ARROW_LEFT, CARET_RIGHT, COMPUTER_TOWER, FOLDER_LOCK, FOLDER_OPEN, GEAR, GLOBE, GLOBE_SIMPLE, LOCK_KEY, PLUS, SIDEBAR_SIMPLE, SPINNER, SUITCASE, WARNING_CIRCLE};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, Root, TitlePanel, View};
use crate::gui::views::{Modal, Content, TitlePanel, View};
use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions, TitleContentType, TitleType};
use crate::gui::views::wallets::creation::WalletCreation;
use crate::gui::views::wallets::types::WalletTabType;
@ -103,19 +103,22 @@ impl WalletsContent {
let wallet_panel_width = self.wallet_panel_width(ui, empty_list, dual_panel, show_wallet);
let content_width = ui.available_width();
let root_dual_panel = Root::is_dual_panel_mode(ui);
let root_dual_panel = Content::is_dual_panel_mode(ui);
// Flag to check if wallet list is hidden on the screen.
let list_hidden = content_width == 0.0 || empty_list || create_wallet
|| (dual_panel && show_wallet && !self.show_wallets_at_dual_panel)
|| (!dual_panel && show_wallet) ||
(!root_dual_panel && Root::is_network_panel_open());
(!root_dual_panel && Content::is_network_panel_open());
let wallet_panel_opened = self.wallet_panel_opened();
// Show title panel.
if !list_hidden || wallet_panel_opened {
self.title_ui(ui, dual_panel, create_wallet, show_wallet);
}
// Show wallet panel content.
let wallet_panel_opened = self.wallet_panel_opened();
egui::SidePanel::right("wallet_panel")
.resizable(false)
.exact_width(wallet_panel_width)
@ -133,10 +136,10 @@ impl WalletsContent {
..Default::default()
})
.show_animated_inside(ui, wallet_panel_opened, |ui| {
// // Do not draw content on zero width.
// if content_width == 0.0 {
// return;
// }
// Do not draw content on zero width.
if content_width == 0.0 {
return;
}
if create_wallet || !show_wallet {
// Show wallet creation content.
self.creation_content.ui(ui, cb, |wallet| {
@ -155,7 +158,7 @@ impl WalletsContent {
let mut rect = ui.available_rect_before_wrap();
let mut width = ui.available_width();
if dual_panel && self.show_wallets_at_dual_panel {
width = content_width - Root::SIDE_PANEL_WIDTH;
width = content_width - Content::SIDE_PANEL_WIDTH;
}
rect.set_width(width);
// Show wallet content.
@ -168,11 +171,8 @@ impl WalletsContent {
}
});
// Setup flag to show wallets bottom panel if wallet is not showing
// at non-dual panel mode and network is no open or showing at dual panel mode.
let show_bottom_panel = !list_hidden || dual_panel;
// Show wallets bottom panel.
let show_bottom_panel = !list_hidden || dual_panel;
if show_bottom_panel {
egui::TopBottomPanel::bottom("wallets_bottom_panel")
.frame(egui::Frame {
@ -305,15 +305,15 @@ impl WalletsContent {
self.show_wallets_at_dual_panel = !show_list;
AppConfig::toggle_show_wallets_at_dual_panel();
});
} else if !Root::is_dual_panel_mode(ui) {
} else if !Content::is_dual_panel_mode(ui) {
View::title_button_big(ui, GLOBE, |_| {
Root::toggle_network_panel();
Content::toggle_network_panel();
});
};
}, |ui| {
View::title_button_big(ui, GEAR, |_| {
// Show settings modal.
Modal::new(Root::SETTINGS_MODAL)
Modal::new(Content::SETTINGS_MODAL)
.position(ModalPosition::CenterTop)
.title(t!("settings"))
.show();
@ -334,10 +334,10 @@ impl WalletsContent {
|| (show_wallet && !self.show_wallets_at_dual_panel) {
ui.available_width()
} else {
ui.available_width() - Root::SIDE_PANEL_WIDTH
ui.available_width() - Content::SIDE_PANEL_WIDTH
};
if dual_panel && show_wallet && self.show_wallets_at_dual_panel {
let min_width = Root::SIDE_PANEL_WIDTH + View::get_right_inset();
let min_width = Content::SIDE_PANEL_WIDTH + View::get_right_inset();
f32::max(min_width, available_width)
} else {
available_width
@ -354,7 +354,7 @@ impl WalletsContent {
.auto_shrink([false; 2])
.show(ui, |ui| {
ui.vertical_centered(|ui| {
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
// Show application logo and name.
View::app_logo_name_version(ui);
ui.add_space(15.0);
@ -613,7 +613,7 @@ impl WalletsContent {
/// Check if it's possible to show [`WalletsContent`] and [`WalletContent`] panels at same time.
fn is_dual_panel_mode(ui: &mut egui::Ui) -> bool {
let dual_panel_root = Root::is_dual_panel_mode(ui);
let dual_panel_root = Content::is_dual_panel_mode(ui);
let max_width = ui.available_width();
dual_panel_root && max_width >= (Root::SIDE_PANEL_WIDTH * 2.0) + View::get_right_inset()
dual_panel_root && max_width >= (Content::SIDE_PANEL_WIDTH * 2.0) + View::get_right_inset()
}

View file

@ -19,7 +19,7 @@ use grin_util::ZeroingString;
use crate::gui::Colors;
use crate::gui::icons::{CHECK, CLIPBOARD_TEXT, COPY, FOLDER_PLUS, SCAN, SHARE_FAT};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, Root, View};
use crate::gui::views::{Modal, Content, View};
use crate::gui::views::types::{ModalPosition, TextEditOptions};
use crate::gui::views::wallets::creation::MnemonicSetup;
use crate::gui::views::wallets::creation::types::Step;
@ -84,7 +84,7 @@ impl WalletCreation {
.show_inside(ui, |ui| {
ui.vertical_centered(|ui| {
ui.vertical_centered(|ui| {
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 2.0, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 2.0, |ui| {
self.step_control_ui(ui, on_create, cb);
});
});
@ -118,9 +118,9 @@ impl WalletCreation {
.show(ui, |ui| {
ui.vertical_centered(|ui| {
let max_width = if self.step == Some(Step::SetupConnection) {
Root::SIDE_PANEL_WIDTH * 1.3
Content::SIDE_PANEL_WIDTH * 1.3
} else {
Root::SIDE_PANEL_WIDTH * 2.0
Content::SIDE_PANEL_WIDTH * 2.0
};
View::max_width_ui(ui, max_width, |ui| {
self.step_content_ui(ui, cb);

View file

@ -17,7 +17,7 @@ use egui::{Id, RichText};
use crate::gui::Colors;
use crate::gui::icons::PENCIL;
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{CameraContent, Modal, Root, View};
use crate::gui::views::{CameraContent, Modal, Content, View};
use crate::gui::views::types::{ModalContainer, ModalPosition, QrScanResult, TextEditOptions};
use crate::wallet::Mnemonic;
use crate::wallet::types::{PhraseMode, PhraseSize};
@ -434,7 +434,7 @@ impl MnemonicSetup {
/// Calculate word list columns count based on available ui width.
fn list_columns_count(ui: &mut egui::Ui) -> usize {
let w = ui.available_width();
let min_panel_w = Root::SIDE_PANEL_WIDTH - 12.0;
let min_panel_w = Content::SIDE_PANEL_WIDTH - 12.0;
let double_min_panel_w = min_panel_w * 2.0;
if w >= min_panel_w * 1.5 && w < double_min_panel_w {
3

View file

@ -22,7 +22,7 @@ use crate::AppConfig;
use crate::gui::Colors;
use crate::gui::icons::{ARROWS_CLOCKWISE, BRIDGE, CHAT_CIRCLE_TEXT, CHECK, CHECK_FAT, COPY, FOLDER_USER, GEAR_FINE, GRAPH, PACKAGE, PATH, POWER, SCAN, SPINNER, USERS_THREE};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{CameraContent, Modal, Root, View};
use crate::gui::views::{CameraContent, Modal, Content, View};
use crate::gui::views::types::{ModalPosition, QrScanResult, TextEditOptions};
use crate::gui::views::wallets::{WalletTransactions, WalletMessages, WalletTransport, WalletSettings};
use crate::gui::views::wallets::types::{GRIN, WalletTab, WalletTabType};
@ -80,7 +80,7 @@ impl WalletContent {
// Show modal content for this ui container.
self.modal_content_ui(ui, wallet, cb);
let dual_panel = Root::is_dual_panel_mode(ui);
let dual_panel = Content::is_dual_panel_mode(ui);
let data = wallet.get_data();
let data_empty = data.is_none();
@ -124,7 +124,7 @@ impl WalletContent {
ui.add_space(1.0);
}
// Draw account info.
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
self.account_ui(ui, wallet, data.unwrap(), cb);
});
});
@ -146,7 +146,7 @@ impl WalletContent {
.show_animated_inside(ui, show_tabs, |ui| {
ui.vertical_centered(|ui| {
// Draw wallet tabs.
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
self.tabs_ui(ui, wallet);
});
});
@ -576,13 +576,13 @@ impl WalletContent {
} else if wallet.get_current_ext_conn().is_none() {
if !Node::is_running() || Node::is_stopping() {
View::center_content(ui, 108.0, |ui| {
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.5, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.5, |ui| {
let text = t!("wallets.enable_node", "settings" => GEAR_FINE);
ui.label(RichText::new(text).size(16.0).color(Colors::inactive_text()));
ui.add_space(8.0);
// Show button to enable integrated node at non-dual root panel mode
// or when network connections are not showing and node is not stopping
let dual_panel_root = Root::is_dual_panel_mode(ui);
let dual_panel_root = Content::is_dual_panel_mode(ui);
if (!dual_panel_root || AppConfig::show_connections_network_panel())
&& !Node::is_stopping() {
let enable_text = format!("{} {}", POWER, t!("network.enable_node"));
@ -640,7 +640,7 @@ impl WalletContent {
/// Draw wallet sync progress content.
pub fn sync_progress_ui(ui: &mut egui::Ui, wallet: &Wallet) {
View::center_content(ui, 162.0, |ui| {
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.5, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.5, |ui| {
View::big_loading_spinner(ui);
ui.add_space(18.0);
// Setup sync progress text.

View file

@ -24,7 +24,7 @@ use parking_lot::RwLock;
use crate::gui::Colors;
use crate::gui::icons::{BROOM, CLIPBOARD_TEXT, COPY, DOWNLOAD_SIMPLE, PROHIBIT, QR_CODE, SCAN, UPLOAD_SIMPLE};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{CameraContent, FilePickButton, Modal, QrCodeContent, Root, View};
use crate::gui::views::{CameraContent, FilePickButton, Modal, QrCodeContent, Content, View};
use crate::gui::views::types::{ModalPosition, QrScanResult, TextEditOptions};
use crate::gui::views::wallets::wallet::types::{SLATEPACK_MESSAGE_HINT, WalletTab, WalletTabType};
use crate::gui::views::wallets::wallet::WalletContent;
@ -144,7 +144,7 @@ impl WalletTab for WalletMessages {
.auto_shrink([false; 2])
.show(ui, |ui| {
ui.vertical_centered(|ui| {
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
self.ui(ui, wallet, cb);
});
});

View file

@ -17,7 +17,7 @@ use egui::scroll_area::ScrollBarVisibility;
use crate::gui::Colors;
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Root, View};
use crate::gui::views::{Content, View};
use crate::gui::views::wallets::setup::{CommonSetup, ConnectionSetup, RecoverySetup};
use crate::gui::views::wallets::wallet::types::{WalletTab, WalletTabType};
use crate::gui::views::wallets::wallet::WalletContent;
@ -80,7 +80,7 @@ impl WalletTab for WalletSettings {
.scroll_bar_visibility(ScrollBarVisibility::AlwaysHidden)
.show(ui, |ui| {
ui.vertical_centered(|ui| {
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
// Show common wallet setup.
self.common_setup.ui(ui, wallet, cb);
// Show wallet connections setup.

View file

@ -26,7 +26,7 @@ use grin_wallet_libwallet::SlatepackAddress;
use crate::gui::Colors;
use crate::gui::icons::{CHECK_CIRCLE, COPY, DOTS_THREE_CIRCLE, EXPORT, GEAR_SIX, GLOBE_SIMPLE, POWER, QR_CODE, SHIELD_CHECKERED, SHIELD_SLASH, WARNING_CIRCLE, X_CIRCLE};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{CameraContent, Modal, QrCodeContent, Root, View};
use crate::gui::views::{CameraContent, Modal, QrCodeContent, Content, View};
use crate::gui::views::types::{ModalPosition, TextEditOptions};
use crate::gui::views::wallets::wallet::types::{WalletTab, WalletTabType};
use crate::gui::views::wallets::wallet::WalletContent;
@ -106,7 +106,7 @@ impl WalletTab for WalletTransport {
.auto_shrink([false; 2])
.show(ui, |ui| {
ui.vertical_centered(|ui| {
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
self.ui(ui, wallet, cb);
});
});

View file

@ -25,7 +25,7 @@ use parking_lot::RwLock;
use crate::gui::Colors;
use crate::gui::icons::{ARROW_CIRCLE_DOWN, ARROW_CIRCLE_UP, ARROW_CLOCKWISE, BRIDGE, BROOM, CALENDAR_CHECK, CHAT_CIRCLE_TEXT, CHECK, CHECK_CIRCLE, CLIPBOARD_TEXT, COPY, DOTS_THREE_CIRCLE, FILE_ARCHIVE, FILE_TEXT, GEAR_FINE, HASH_STRAIGHT, PROHIBIT, QR_CODE, SCAN, X_CIRCLE};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{CameraContent, FilePickButton, Modal, PullToRefresh, QrCodeContent, Root, View};
use crate::gui::views::{CameraContent, FilePickButton, Modal, PullToRefresh, QrCodeContent, Content, View};
use crate::gui::views::types::ModalPosition;
use crate::gui::views::wallets::types::WalletTab;
use crate::gui::views::wallets::wallet::types::{GRIN, SLATEPACK_MESSAGE_HINT, WalletTabType};
@ -145,7 +145,7 @@ impl WalletTransactions {
let amount_conf = data.info.amount_awaiting_confirmation;
let amount_fin = data.info.amount_awaiting_finalization;
let amount_locked = data.info.amount_locked;
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
// Show non-zero awaiting confirmation amount.
if amount_conf != 0 {
let awaiting_conf = amount_to_hr_string(amount_conf, true);
@ -222,7 +222,7 @@ impl WalletTransactions {
.auto_shrink([false; 2])
.show_rows(ui, TX_ITEM_HEIGHT, txs.len(), |ui, row_range| {
ui.add_space(1.0);
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| {
let padding = amount_conf != 0 || amount_fin != 0 || amount_locked != 0;
for index in row_range {
let tx = txs.get(index).unwrap();

View file

@ -69,9 +69,14 @@ fn real_main() {
}
// Setup window decorations.
let is_mac_os = OperatingSystem::from_target_os() == OperatingSystem::Mac;
viewport = viewport
.with_fullsize_content_view(true)
.with_title_shown(false)
.with_titlebar_buttons_shown(false)
.with_titlebar_shown(false)
.with_transparent(true)
.with_decorations(false);
.with_decorations(is_mac_os);
let mut options = eframe::NativeOptions {
viewport,

View file

@ -14,7 +14,7 @@
use grin_core::global::ChainTypes;
use serde_derive::{Deserialize, Serialize};
use crate::gui::views::Root;
use crate::gui::views::Content;
use crate::node::{NodeConfig, PeersConfig};
use crate::Settings;
@ -71,15 +71,15 @@ impl Default for AppConfig {
impl AppConfig {
/// Desktop window frame margin sum, horizontal or vertical.
const FRAME_MARGIN: f32 = Root::WINDOW_FRAME_MARGIN * 2.0;
const FRAME_MARGIN: f32 = Content::WINDOW_FRAME_MARGIN * 2.0;
/// Default desktop window width.
pub const DEFAULT_WIDTH: f32 = Root::SIDE_PANEL_WIDTH * 3.0 + Self::FRAME_MARGIN;
pub const DEFAULT_WIDTH: f32 = Content::SIDE_PANEL_WIDTH * 3.0 + Self::FRAME_MARGIN;
/// Default desktop window height.
pub const DEFAULT_HEIGHT: f32 = 706.0;
/// Minimal desktop window width.
pub const MIN_WIDTH: f32 = Root::SIDE_PANEL_WIDTH + Self::FRAME_MARGIN;
pub const MIN_WIDTH: f32 = Content::SIDE_PANEL_WIDTH + Self::FRAME_MARGIN;
/// Minimal desktop window height.
pub const MIN_HEIGHT: f32 = 630.0 + Root::WINDOW_TITLE_HEIGHT + Self::FRAME_MARGIN;
pub const MIN_HEIGHT: f32 = 630.0 + Content::WINDOW_TITLE_HEIGHT + Self::FRAME_MARGIN;
/// Application configuration file name.
pub const FILE_NAME: &'static str = "app.toml";