ui: modal refactoring, update some translations, optimize port text edit size and network messages when node is stopping
This commit is contained in:
parent
4682560763
commit
7f1c6579b1
11 changed files with 171 additions and 225 deletions
|
@ -10,7 +10,7 @@ network:
|
||||||
disable: Disable
|
disable: Disable
|
||||||
restart: Restart
|
restart: Restart
|
||||||
autorun: Autorun
|
autorun: Autorun
|
||||||
disabled_server: 'Enable integrated node or choose another connection method by pressing %{dots} in the top-left corner of the screen.'
|
disabled_server: 'Enable integrated node or add another connection method by pressing %{dots} in the top-left corner of the screen.'
|
||||||
sync_status:
|
sync_status:
|
||||||
node_restarting: Node is restarting
|
node_restarting: Node is restarting
|
||||||
node_down: Node is down
|
node_down: Node is down
|
||||||
|
@ -58,7 +58,7 @@ network_mining:
|
||||||
server_setup: Stratum server setup
|
server_setup: Stratum server setup
|
||||||
enable_server: Enable server
|
enable_server: Enable server
|
||||||
server_setting: 'Enable stratum server or change more settings by selecting %{settings} at the bottom of the screen. App restart is required to change settings of the running server.'
|
server_setting: 'Enable stratum server or change more settings by selecting %{settings} at the bottom of the screen. App restart is required to change settings of the running server.'
|
||||||
info: 'Mining server is enabled, you can change settings by selecting %{settings} at the bottom of the screen. Data is updating when devices are connected.'
|
info: 'Mining server is enabled, you can change its settings by selecting %{settings} at the bottom of the screen. Data is updating when devices are connected.'
|
||||||
no_ip_addresses: There are no available IP addresses on your system, stratum server cannot be started, check your network connectivity.
|
no_ip_addresses: There are no available IP addresses on your system, stratum server cannot be started, check your network connectivity.
|
||||||
port_unavailable: Specified port is unavailable
|
port_unavailable: Specified port is unavailable
|
||||||
rewards_wallet: Wallet for rewards
|
rewards_wallet: Wallet for rewards
|
||||||
|
|
|
@ -10,7 +10,7 @@ network:
|
||||||
disable: Выключить
|
disable: Выключить
|
||||||
restart: Перезапустить
|
restart: Перезапустить
|
||||||
autorun: Автозапуск
|
autorun: Автозапуск
|
||||||
disabled_server: 'Включите встроенный узел или выберите другой способ подключения, нажав %{dots} в левом-верхнем углу экрана.'
|
disabled_server: 'Включите встроенный узел или добавьте другой способ подключения, нажав %{dots} в левом-верхнем углу экрана.'
|
||||||
sync_status:
|
sync_status:
|
||||||
node_restarting: Узел перезапускается
|
node_restarting: Узел перезапускается
|
||||||
node_down: Узел выключен
|
node_down: Узел выключен
|
||||||
|
@ -58,7 +58,7 @@ network_mining:
|
||||||
server_setup: Настройка stratum-сервера
|
server_setup: Настройка stratum-сервера
|
||||||
enable_server: Включить сервер
|
enable_server: Включить сервер
|
||||||
server_setting: 'Включите stratum-сервер или измените больше настроек, выбрав %{settings} внизу экрана. Для изменения настроек запущенного сервера потребуется перезапуск приложения.'
|
server_setting: 'Включите stratum-сервер или измените больше настроек, выбрав %{settings} внизу экрана. Для изменения настроек запущенного сервера потребуется перезапуск приложения.'
|
||||||
info: 'Сервер майнинга запущен, вы можете изменить настройки, выбрав %{settings} внизу экрана. Данные обновляются, когда устройства подключены.'
|
info: 'Сервер майнинга запущен, вы можете изменить его настройки, выбрав %{settings} внизу экрана. Данные обновляются, когда устройства подключены.'
|
||||||
no_ip_addresses: В вашей системе отсутствуют доступные IP адреса, запуск stratum-сервера невозможен, проверьте ваше подключение к сети.
|
no_ip_addresses: В вашей системе отсутствуют доступные IP адреса, запуск stratum-сервера невозможен, проверьте ваше подключение к сети.
|
||||||
port_unavailable: Указанный порт недоступен
|
port_unavailable: Указанный порт недоступен
|
||||||
rewards_wallet: Кошелёк для наград
|
rewards_wallet: Кошелёк для наград
|
||||||
|
|
|
@ -19,25 +19,21 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
use crate::gui::screens::ScreenId;
|
use crate::gui::screens::ScreenId;
|
||||||
use crate::gui::views::{Modal, ModalLocation};
|
use crate::gui::views::Modal;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// Static [`Navigator`] state to be accessible from anywhere.
|
/// Static [`Navigator`] state to be accessible from anywhere.
|
||||||
static ref NAVIGATOR_STATE: RwLock<Navigator> = RwLock::new(Navigator::default());
|
static ref NAVIGATOR_STATE: RwLock<Navigator> = RwLock::new(Navigator::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Logic of navigation for UI, stores screen identifiers stack, open modals and side panel state.
|
/// Logic of navigation at ui, stores screen identifiers stack, showing modal and side panel state.
|
||||||
pub struct Navigator {
|
pub struct Navigator {
|
||||||
/// Screen identifiers in navigation stack.
|
/// Screen identifiers in navigation stack.
|
||||||
screen_stack: BTreeSet<ScreenId>,
|
screen_stack: BTreeSet<ScreenId>,
|
||||||
/// Indicator if side panel is open.
|
/// Indicator if side panel is open.
|
||||||
side_panel_open: AtomicBool,
|
side_panel_open: AtomicBool,
|
||||||
/// Modal state to show globally above panel and screen.
|
/// Modal window to show.
|
||||||
global_modal: Option<Modal>,
|
modal: Option<Modal>,
|
||||||
/// Modal state to show on the side panel.
|
|
||||||
side_panel_modal: Option<Modal>,
|
|
||||||
/// Modal state to show on the screen.
|
|
||||||
screen_modal: Option<Modal>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Navigator {
|
impl Default for Navigator {
|
||||||
|
@ -45,9 +41,7 @@ impl Default for Navigator {
|
||||||
Self {
|
Self {
|
||||||
screen_stack: BTreeSet::new(),
|
screen_stack: BTreeSet::new(),
|
||||||
side_panel_open: AtomicBool::new(false),
|
side_panel_open: AtomicBool::new(false),
|
||||||
global_modal: None,
|
modal: None,
|
||||||
side_panel_modal: None,
|
|
||||||
screen_modal: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,119 +72,72 @@ impl Navigator {
|
||||||
pub fn back() {
|
pub fn back() {
|
||||||
let mut w_nav = NAVIGATOR_STATE.write().unwrap();
|
let mut w_nav = NAVIGATOR_STATE.write().unwrap();
|
||||||
|
|
||||||
// If global Modal is showing and closeable, remove it from Navigator.
|
// If Modal is showing and closeable, remove it from Navigator.
|
||||||
if w_nav.global_modal.is_some() {
|
if w_nav.modal.is_some() {
|
||||||
let global_modal = w_nav.global_modal.as_ref().unwrap();
|
let modal = w_nav.modal.as_ref().unwrap();
|
||||||
if global_modal.is_closeable() {
|
if modal.is_closeable() {
|
||||||
w_nav.global_modal = None;
|
w_nav.modal = None;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If side panel Modal is showing and closeable, remove it from Navigator.
|
// Go back at screen stack or set exit confirmation Modal.
|
||||||
if w_nav.side_panel_modal.is_some() {
|
|
||||||
let side_panel_modal = w_nav.side_panel_modal.as_ref().unwrap();
|
|
||||||
if side_panel_modal.is_closeable() {
|
|
||||||
w_nav.side_panel_modal = None;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If screen Modal is showing and closeable, remove it from Navigator.
|
|
||||||
if w_nav.screen_modal.is_some() {
|
|
||||||
let screen_modal = w_nav.screen_modal.as_ref().unwrap();
|
|
||||||
if screen_modal.is_closeable() {
|
|
||||||
w_nav.screen_modal = None;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go back at screen stack or show exit confirmation Modal.
|
|
||||||
if w_nav.screen_stack.len() > 1 {
|
if w_nav.screen_stack.len() > 1 {
|
||||||
w_nav.screen_stack.pop_last();
|
w_nav.screen_stack.pop_last();
|
||||||
} else {
|
} else {
|
||||||
Self::open_exit_modal_nav(w_nav);
|
Self::show_exit_modal_nav(w_nav);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open exit confirmation [`Modal`].
|
/// Set exit confirmation [`Modal`].
|
||||||
pub fn open_exit_modal() {
|
pub fn show_exit_modal() {
|
||||||
let w_nav = NAVIGATOR_STATE.write().unwrap();
|
let w_nav = NAVIGATOR_STATE.write().unwrap();
|
||||||
Self::open_exit_modal_nav(w_nav);
|
Self::show_exit_modal_nav(w_nav);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open exit confirmation [`Modal`] with provided [NAVIGATOR_STATE] lock.
|
/// Set exit confirmation [`Modal`] with provided [NAVIGATOR_STATE] lock.
|
||||||
fn open_exit_modal_nav(mut w_nav: RwLockWriteGuard<Navigator>) {
|
fn show_exit_modal_nav(mut w_nav: RwLockWriteGuard<Navigator>) {
|
||||||
let m = Modal::new(Self::EXIT_MODAL, ModalLocation::Global).title(t!("modal_exit.exit"));
|
let m = Modal::new(Self::EXIT_MODAL).title(t!("modal_exit.exit"));
|
||||||
w_nav.global_modal = Some(m);
|
w_nav.modal = Some(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open [`Modal`] at specified location.
|
/// Set [`Modal`] to show.
|
||||||
pub fn open_modal(modal: Modal) {
|
pub fn show_modal(modal: Modal) {
|
||||||
let mut w_nav = NAVIGATOR_STATE.write().unwrap();
|
let mut w_nav = NAVIGATOR_STATE.write().unwrap();
|
||||||
match modal.location {
|
w_nav.modal = Some(modal);
|
||||||
ModalLocation::Global => {
|
|
||||||
w_nav.global_modal = Some(modal);
|
|
||||||
}
|
|
||||||
ModalLocation::SidePanel => {
|
|
||||||
w_nav.side_panel_modal = Some(modal);
|
|
||||||
}
|
|
||||||
ModalLocation::Screen => {
|
|
||||||
w_nav.screen_modal = Some(modal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if [`Modal`] is open at specified location and remove it from [`Navigator`] otherwise.
|
/// Check if [`Modal`] is open by returning its id, remove it from [`Navigator`] if it's closed.
|
||||||
pub fn is_modal_open(location: ModalLocation) -> bool {
|
pub fn is_modal_open() -> Option<&'static str> {
|
||||||
// Check if Modal is showing.
|
// Check if Modal is showing.
|
||||||
{
|
{
|
||||||
let r_nav = NAVIGATOR_STATE.read().unwrap();
|
if NAVIGATOR_STATE.read().unwrap().modal.is_none() {
|
||||||
let showing = match location {
|
return None;
|
||||||
ModalLocation::Global => { r_nav.global_modal.is_some() }
|
|
||||||
ModalLocation::SidePanel => { r_nav.side_panel_modal.is_some() }
|
|
||||||
ModalLocation::Screen => { r_nav.screen_modal.is_some() }
|
|
||||||
};
|
|
||||||
if !showing {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if Modal is open.
|
// Check if Modal is open.
|
||||||
let is_open = {
|
let (is_open, id) = {
|
||||||
let r_nav = NAVIGATOR_STATE.read().unwrap();
|
let r_nav = NAVIGATOR_STATE.read().unwrap();
|
||||||
match location {
|
let modal = r_nav.modal.as_ref().unwrap();
|
||||||
ModalLocation::Global => { r_nav.global_modal.as_ref().unwrap().is_open() }
|
(modal.is_open(), modal.id)
|
||||||
ModalLocation::SidePanel => { r_nav.side_panel_modal.as_ref().unwrap().is_open() }
|
|
||||||
ModalLocation::Screen => {r_nav.screen_modal.as_ref().unwrap().is_open() }
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// If Modal is not open, remove it from navigator state.
|
// If Modal is not open, remove it from navigator state.
|
||||||
if !is_open {
|
if !is_open {
|
||||||
let mut w_nav = NAVIGATOR_STATE.write().unwrap();
|
let mut w_nav = NAVIGATOR_STATE.write().unwrap();
|
||||||
match location {
|
w_nav.modal = None;
|
||||||
ModalLocation::Global => { w_nav.global_modal = None }
|
return None;
|
||||||
ModalLocation::SidePanel => { w_nav.side_panel_modal = None }
|
|
||||||
ModalLocation::Screen => { w_nav.screen_modal = None }
|
|
||||||
}
|
}
|
||||||
return false;
|
Some(id)
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show [`Modal`] with provided location at app UI.
|
/// Draw showing [`Modal`] content if it's opened.
|
||||||
pub fn modal_ui(ui: &mut egui::Ui,
|
pub fn modal_ui(ui: &mut egui::Ui, add_content: impl FnOnce(&mut egui::Ui, &Modal)) {
|
||||||
location: ModalLocation,
|
if let Some(modal) = &NAVIGATOR_STATE.read().unwrap().modal {
|
||||||
add_content: impl FnOnce(&mut egui::Ui, &Modal)) {
|
if modal.is_open() {
|
||||||
let r_nav = NAVIGATOR_STATE.read().unwrap();
|
modal.ui(ui, add_content);
|
||||||
let modal = match location {
|
}
|
||||||
ModalLocation::Global => { &r_nav.global_modal }
|
|
||||||
ModalLocation::SidePanel => { &r_nav.side_panel_modal }
|
|
||||||
ModalLocation::Screen => { &r_nav.screen_modal }
|
|
||||||
};
|
|
||||||
if modal.is_some() {
|
|
||||||
modal.as_ref().unwrap().ui(ui, add_content);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,17 +13,17 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
||||||
use crate::gui::{App, Colors, Navigator};
|
use crate::gui::{App, Colors, Navigator};
|
||||||
use crate::gui::platform::PlatformCallbacks;
|
use crate::gui::platform::PlatformCallbacks;
|
||||||
use crate::gui::screens::{Account, Accounts, Screen, ScreenId};
|
use crate::gui::screens::{Account, Accounts, Screen, ScreenId};
|
||||||
use crate::gui::views::{ModalLocation, Network, View};
|
use crate::gui::views::{ModalContainer, Network, View};
|
||||||
use crate::node::Node;
|
use crate::node::Node;
|
||||||
|
|
||||||
pub struct Root {
|
pub struct Root {
|
||||||
screens: Vec<Box<dyn Screen>>,
|
screens: Vec<Box<dyn Screen>>,
|
||||||
network: Network,
|
network: Network,
|
||||||
show_exit_progress: bool
|
show_exit_progress: bool,
|
||||||
|
allowed_modal_ids: Vec<&'static str>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Root {
|
impl Default for Root {
|
||||||
|
@ -31,23 +31,34 @@ impl Default for Root {
|
||||||
Navigator::init(ScreenId::Accounts);
|
Navigator::init(ScreenId::Accounts);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
screens: (vec![
|
screens: vec![
|
||||||
Box::new(Accounts::default()),
|
Box::new(Accounts::default()),
|
||||||
Box::new(Account::default())
|
Box::new(Account::default())
|
||||||
]),
|
],
|
||||||
network: Network::default(),
|
network: Network::default(),
|
||||||
show_exit_progress: false
|
show_exit_progress: false,
|
||||||
|
allowed_modal_ids: vec![
|
||||||
|
Navigator::EXIT_MODAL
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ModalContainer for Root {
|
||||||
|
fn allowed_modal_ids(&self) -> &Vec<&'static str> {
|
||||||
|
self.allowed_modal_ids.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Root {
|
impl Root {
|
||||||
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
|
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
|
||||||
if Navigator::is_modal_open(ModalLocation::Global) {
|
// Draw exit modal content if it's open.
|
||||||
self.show_global_modal(ui, frame, cb);
|
let modal_id = Navigator::is_modal_open();
|
||||||
|
if modal_id.is_some() && self.can_show_modal(modal_id.unwrap()) {
|
||||||
|
self.exit_modal_content(ui, frame, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (is_panel_open, panel_width) = self.dual_panel_state_width(frame);
|
let (is_panel_open, panel_width) = Self::side_panel_state_width(frame);
|
||||||
egui::SidePanel::left("network_panel")
|
egui::SidePanel::left("network_panel")
|
||||||
.resizable(false)
|
.resizable(false)
|
||||||
.exact_width(panel_width)
|
.exact_width(panel_width)
|
||||||
|
@ -63,13 +74,11 @@ impl Root {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_global_modal(&mut self,
|
fn exit_modal_content(&mut self,
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
frame: &mut eframe::Frame,
|
frame: &mut eframe::Frame,
|
||||||
cb: &dyn PlatformCallbacks) {
|
cb: &dyn PlatformCallbacks) {
|
||||||
Navigator::modal_ui(ui, ModalLocation::Global, |ui, modal| {
|
Navigator::modal_ui(ui, |ui, modal| {
|
||||||
match modal.id {
|
|
||||||
Navigator::EXIT_MODAL => {
|
|
||||||
if self.show_exit_progress {
|
if self.show_exit_progress {
|
||||||
if !Node::is_running() {
|
if !Node::is_running() {
|
||||||
App::exit(frame, cb);
|
App::exit(frame, cb);
|
||||||
|
@ -116,9 +125,6 @@ impl Root {
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,8 +141,8 @@ impl Root {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get dual panel state and width
|
/// Get side panel state and width.
|
||||||
fn dual_panel_state_width(&self, frame: &mut eframe::Frame) -> (bool, f32) {
|
fn side_panel_state_width(frame: &mut eframe::Frame) -> (bool, f32) {
|
||||||
let dual_panel_mode = View::is_dual_panel_mode(frame);
|
let dual_panel_mode = View::is_dual_panel_mode(frame);
|
||||||
let is_panel_open = dual_panel_mode || Navigator::is_side_panel_open();
|
let is_panel_open = dual_panel_mode || Navigator::is_side_panel_open();
|
||||||
let panel_width = if dual_panel_mode {
|
let panel_width = if dual_panel_mode {
|
||||||
|
|
|
@ -15,27 +15,25 @@
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
use egui::{Align2, RichText, Rounding, Sense, Stroke, Vec2};
|
use egui::{Align2, RichText, Rounding, Stroke, Vec2};
|
||||||
use egui::epaint::RectShape;
|
use egui::epaint::RectShape;
|
||||||
|
|
||||||
use crate::gui::Colors;
|
use crate::gui::Colors;
|
||||||
use crate::gui::views::View;
|
use crate::gui::views::View;
|
||||||
|
|
||||||
/// Location for [`Modal`] at application UI.
|
/// Contains modal ids to draw at current container if possible.
|
||||||
pub enum ModalLocation {
|
pub trait ModalContainer {
|
||||||
/// To draw globally above side panel and screen.
|
fn allowed_modal_ids(&self) -> &Vec<&'static str>;
|
||||||
Global,
|
|
||||||
/// To draw on the side panel.
|
/// Check if it's possible to show modal.
|
||||||
SidePanel,
|
fn can_show_modal(&self, id: &'static str) -> bool {
|
||||||
/// To draw on the screen.
|
self.allowed_modal_ids().contains(&id)
|
||||||
Screen
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Position of [`Modal`] on the screen at provided [`ModalLocation`].
|
/// Position of [`Modal`] on the screen.
|
||||||
pub enum ModalPosition {
|
pub enum ModalPosition {
|
||||||
/// Center-top position.
|
|
||||||
CenterTop,
|
CenterTop,
|
||||||
/// Center of the location.
|
|
||||||
Center
|
Center
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,8 +41,6 @@ pub enum ModalPosition {
|
||||||
pub struct Modal {
|
pub struct Modal {
|
||||||
/// Identifier for modal.
|
/// Identifier for modal.
|
||||||
pub(crate) id: &'static str,
|
pub(crate) id: &'static str,
|
||||||
/// Location at UI.
|
|
||||||
pub(crate) location: ModalLocation,
|
|
||||||
/// Position on the screen.
|
/// Position on the screen.
|
||||||
position: ModalPosition,
|
position: ModalPosition,
|
||||||
/// Flag to show the content.
|
/// Flag to show the content.
|
||||||
|
@ -59,11 +55,10 @@ impl Modal {
|
||||||
/// Default width of the content.
|
/// Default width of the content.
|
||||||
const DEFAULT_WIDTH: i64 = 380;
|
const DEFAULT_WIDTH: i64 = 380;
|
||||||
|
|
||||||
/// Create open and closeable Modal with center position.
|
/// Create opened and closeable Modal with center position.
|
||||||
pub fn new(id: &'static str, location: ModalLocation) -> Self {
|
pub fn new(id: &'static str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
location,
|
|
||||||
position: ModalPosition::Center,
|
position: ModalPosition::Center,
|
||||||
open: AtomicBool::new(true),
|
open: AtomicBool::new(true),
|
||||||
closeable: AtomicBool::new(true),
|
closeable: AtomicBool::new(true),
|
||||||
|
@ -112,12 +107,11 @@ impl Modal {
|
||||||
/// Show Modal with provided content.
|
/// Show Modal with provided content.
|
||||||
pub fn ui(&self, ui: &mut egui::Ui, add_content: impl FnOnce(&mut egui::Ui, &Modal)) {
|
pub fn ui(&self, ui: &mut egui::Ui, add_content: impl FnOnce(&mut egui::Ui, &Modal)) {
|
||||||
// Show background Window at full available size.
|
// Show background Window at full available size.
|
||||||
egui::Window::new(self.window_id(true))
|
egui::Window::new("modal_bg_window")
|
||||||
.title_bar(false)
|
.title_bar(false)
|
||||||
.resizable(false)
|
.resizable(false)
|
||||||
.collapsible(false)
|
.collapsible(false)
|
||||||
.fixed_pos(ui.next_widget_position())
|
.fixed_size(ui.ctx().used_size())
|
||||||
.fixed_size(ui.available_size())
|
|
||||||
.frame(egui::Frame {
|
.frame(egui::Frame {
|
||||||
fill: Colors::SEMI_TRANSPARENT,
|
fill: Colors::SEMI_TRANSPARENT,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -131,7 +125,7 @@ impl Modal {
|
||||||
|
|
||||||
// Show main content Window at given position.
|
// Show main content Window at given position.
|
||||||
let (content_align, content_offset) = self.modal_position();
|
let (content_align, content_offset) = self.modal_position();
|
||||||
let layer_id = egui::Window::new(self.window_id(false))
|
let layer_id = egui::Window::new("modal_window")
|
||||||
.title_bar(false)
|
.title_bar(false)
|
||||||
.resizable(false)
|
.resizable(false)
|
||||||
.collapsible(false)
|
.collapsible(false)
|
||||||
|
@ -154,21 +148,6 @@ impl Modal {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate identifier for inner [`egui::Window`] parts based on [`ModalLocation`].
|
|
||||||
fn window_id(&self, background: bool) -> &'static str {
|
|
||||||
match self.location {
|
|
||||||
ModalLocation::Global => {
|
|
||||||
if background { "global.bg" } else { "global" }
|
|
||||||
}
|
|
||||||
ModalLocation::SidePanel => {
|
|
||||||
if background { "side_panel.bg" } else { "side_panel" }
|
|
||||||
}
|
|
||||||
ModalLocation::Screen => {
|
|
||||||
if background { "global.bg" } else { "global" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get [`egui::Window`] position based on [`ModalPosition`].
|
/// Get [`egui::Window`] position based on [`ModalPosition`].
|
||||||
fn modal_position(&self) -> (Align2, Vec2) {
|
fn modal_position(&self) -> (Align2, Vec2) {
|
||||||
let align = match self.position {
|
let align = match self.position {
|
||||||
|
|
|
@ -16,7 +16,7 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddrV4, TcpListener};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use egui::{Color32, lerp, Rgba, RichText, Stroke};
|
use egui::{Color32, lerp, Rgba, RichText};
|
||||||
use egui::style::Margin;
|
use egui::style::Margin;
|
||||||
use egui_extras::{Size, StripBuilder};
|
use egui_extras::{Size, StripBuilder};
|
||||||
use grin_chain::SyncStatus;
|
use grin_chain::SyncStatus;
|
||||||
|
@ -24,11 +24,12 @@ use grin_chain::SyncStatus;
|
||||||
use crate::gui::{Colors, Navigator};
|
use crate::gui::{Colors, Navigator};
|
||||||
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE};
|
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE};
|
||||||
use crate::gui::platform::PlatformCallbacks;
|
use crate::gui::platform::PlatformCallbacks;
|
||||||
use crate::gui::views::{Modal, ModalLocation, View};
|
use crate::gui::views::{Modal, ModalContainer, View};
|
||||||
use crate::gui::views::network_metrics::NetworkMetrics;
|
use crate::gui::views::network_metrics::NetworkMetrics;
|
||||||
use crate::gui::views::network_mining::NetworkMining;
|
use crate::gui::views::network_mining::NetworkMining;
|
||||||
use crate::gui::views::network_node::NetworkNode;
|
use crate::gui::views::network_node::NetworkNode;
|
||||||
use crate::gui::views::network_settings::NetworkSettings;
|
use crate::gui::views::network_settings::NetworkSettings;
|
||||||
|
use crate::gui::views::settings_stratum::StratumServerSetup;
|
||||||
use crate::node::Node;
|
use crate::node::Node;
|
||||||
use crate::Settings;
|
use crate::Settings;
|
||||||
|
|
||||||
|
@ -59,21 +60,32 @@ impl NetworkTabType {
|
||||||
|
|
||||||
pub struct Network {
|
pub struct Network {
|
||||||
current_tab: Box<dyn NetworkTab>,
|
current_tab: Box<dyn NetworkTab>,
|
||||||
|
allowed_modal_ids: Vec<&'static str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Network {
|
impl Default for Network {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
current_tab: Box::new(NetworkNode::default()),
|
current_tab: Box::new(NetworkNode::default()),
|
||||||
|
allowed_modal_ids: vec![
|
||||||
|
StratumServerSetup::STRATUM_PORT_MODAL
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ModalContainer for Network {
|
||||||
|
fn allowed_modal_ids(&self) -> &Vec<&'static str> {
|
||||||
|
self.allowed_modal_ids.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Network {
|
impl Network {
|
||||||
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
|
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
|
||||||
// Show modal if it's opened.
|
// Show modal content if it's opened.
|
||||||
if Navigator::is_modal_open(ModalLocation::SidePanel) {
|
let modal_id = Navigator::is_modal_open();
|
||||||
Navigator::modal_ui(ui, ModalLocation::SidePanel, |ui, modal| {
|
if modal_id.is_some() && self.can_show_modal(modal_id.unwrap()) {
|
||||||
|
Navigator::modal_ui(ui, |ui, modal| {
|
||||||
self.current_tab.as_mut().on_modal_ui(ui, modal, cb);
|
self.current_tab.as_mut().on_modal_ui(ui, modal, cb);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,11 +43,13 @@ impl NetworkTab for NetworkMetrics {
|
||||||
} else {
|
} else {
|
||||||
View::center_content(ui, 162.0, |ui| {
|
View::center_content(ui, 162.0, |ui| {
|
||||||
View::big_loading_spinner(ui);
|
View::big_loading_spinner(ui);
|
||||||
|
if !Node::is_stopping() {
|
||||||
ui.add_space(18.0);
|
ui.add_space(18.0);
|
||||||
ui.label(RichText::new(t!("network_metrics.loading"))
|
ui.label(RichText::new(t!("network_metrics.loading"))
|
||||||
.size(16.0)
|
.size(16.0)
|
||||||
.color(Colors::INACTIVE_TEXT)
|
.color(Colors::INACTIVE_TEXT)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||||
use egui::{Response, RichText, Rounding, ScrollArea, Stroke, TextStyle, Widget};
|
use egui::{RichText, Rounding, ScrollArea, Stroke};
|
||||||
use grin_chain::SyncStatus;
|
use grin_chain::SyncStatus;
|
||||||
use grin_servers::WorkerStats;
|
use grin_servers::WorkerStats;
|
||||||
|
|
||||||
use crate::gui::{Colors, Navigator};
|
use crate::gui::Colors;
|
||||||
use crate::gui::icons::{BARBELL, CLOCK_AFTERNOON, COMPUTER_TOWER, CPU, CUBE, FADERS, FOLDER_DASHED, FOLDER_NOTCH_MINUS, FOLDER_NOTCH_PLUS, PLUGS, PLUGS_CONNECTED, POLYGON};
|
use crate::gui::icons::{BARBELL, CLOCK_AFTERNOON, COMPUTER_TOWER, CPU, CUBE, FADERS, FOLDER_DASHED, FOLDER_NOTCH_MINUS, FOLDER_NOTCH_PLUS, PLUGS, PLUGS_CONNECTED, POLYGON};
|
||||||
use crate::gui::platform::PlatformCallbacks;
|
use crate::gui::platform::PlatformCallbacks;
|
||||||
use crate::gui::views::{Modal, Network, NetworkTab, NetworkTabType, View};
|
use crate::gui::views::{Modal, Network, NetworkTab, NetworkTabType, View};
|
||||||
|
@ -45,11 +45,13 @@ impl NetworkTab for NetworkMining {
|
||||||
} else {
|
} else {
|
||||||
View::center_content(ui, 162.0, |ui| {
|
View::center_content(ui, 162.0, |ui| {
|
||||||
View::big_loading_spinner(ui);
|
View::big_loading_spinner(ui);
|
||||||
|
if !Node::is_stopping() {
|
||||||
ui.add_space(18.0);
|
ui.add_space(18.0);
|
||||||
ui.label(RichText::new(t!("network_mining.loading"))
|
ui.label(RichText::new(t!("network_mining.loading"))
|
||||||
.size(16.0)
|
.size(16.0)
|
||||||
.color(Colors::INACTIVE_TEXT)
|
.color(Colors::INACTIVE_TEXT)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -20,7 +20,7 @@ use egui::{RichText, TextStyle, Widget};
|
||||||
use crate::gui::{Colors, Navigator};
|
use crate::gui::{Colors, Navigator};
|
||||||
use crate::gui::icons::WRENCH;
|
use crate::gui::icons::WRENCH;
|
||||||
use crate::gui::platform::PlatformCallbacks;
|
use crate::gui::platform::PlatformCallbacks;
|
||||||
use crate::gui::views::{Modal, ModalLocation, ModalPosition, Network, View};
|
use crate::gui::views::{Modal, ModalPosition, Network, View};
|
||||||
use crate::node::NodeConfig;
|
use crate::node::NodeConfig;
|
||||||
|
|
||||||
/// Stratum server setup ui section.
|
/// Stratum server setup ui section.
|
||||||
|
@ -59,7 +59,7 @@ impl StratumServerSetup {
|
||||||
ui.add_space(4.0);
|
ui.add_space(4.0);
|
||||||
|
|
||||||
// Show error message when IP addresses are not available on the system.
|
// Show error message when IP addresses are not available on the system.
|
||||||
let mut addrs = Network::get_ip_list();
|
let addrs = Network::get_ip_list();
|
||||||
if addrs.is_empty() {
|
if addrs.is_empty() {
|
||||||
ui.vertical_centered(|ui| {
|
ui.vertical_centered(|ui| {
|
||||||
ui.label(RichText::new(t!("network_mining.no_ip_addresses"))
|
ui.label(RichText::new(t!("network_mining.no_ip_addresses"))
|
||||||
|
@ -102,11 +102,10 @@ impl StratumServerSetup {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Show stratum port modal.
|
// Show stratum port modal.
|
||||||
let port_modal = Modal::new(Self::STRATUM_PORT_MODAL,
|
let port_modal = Modal::new(Self::STRATUM_PORT_MODAL)
|
||||||
ModalLocation::SidePanel)
|
|
||||||
.position(ModalPosition::CenterTop)
|
.position(ModalPosition::CenterTop)
|
||||||
.title(t!("network_settings.change_port"));
|
.title(t!("network_settings.change_port"));
|
||||||
Navigator::open_modal(port_modal);
|
Navigator::show_modal(port_modal);
|
||||||
cb.show_keyboard();
|
cb.show_keyboard();
|
||||||
});
|
});
|
||||||
ui.add_space(14.0);
|
ui.add_space(14.0);
|
||||||
|
@ -138,8 +137,8 @@ impl StratumServerSetup {
|
||||||
|
|
||||||
// Draw stratum port text edit.
|
// Draw stratum port text edit.
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.stratum_port_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.stratum_port_edit)
|
||||||
.font(TextStyle::Button)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(48.0)
|
.desired_width(58.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
|
|
@ -12,13 +12,13 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use egui::{AboveOrBelow, Button, PointerState, Response, RichText, ScrollArea, Sense, Spinner, Widget, WidgetText};
|
use egui::{Button, PointerState, Response, RichText, Sense, Spinner, Widget};
|
||||||
use egui::epaint::{Color32, FontId, RectShape, Rounding, Stroke};
|
use egui::epaint::{Color32, FontId, RectShape, Rounding, Stroke};
|
||||||
use egui::epaint::text::TextWrapping;
|
use egui::epaint::text::TextWrapping;
|
||||||
use egui::text::{LayoutJob, TextFormat};
|
use egui::text::{LayoutJob, TextFormat};
|
||||||
|
|
||||||
use crate::gui::Colors;
|
use crate::gui::{Colors, Navigator};
|
||||||
use crate::gui::icons::{CARET_DOWN, CHECK_SQUARE, CIRCLE, RADIO_BUTTON, SQUARE};
|
use crate::gui::icons::{CHECK_SQUARE, SQUARE};
|
||||||
|
|
||||||
pub struct View;
|
pub struct View;
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ impl View {
|
||||||
/// Default width of side panel at application UI.
|
/// Default width of side panel at application UI.
|
||||||
pub const SIDE_PANEL_MIN_WIDTH: i64 = 400;
|
pub const SIDE_PANEL_MIN_WIDTH: i64 = 400;
|
||||||
|
|
||||||
/// Check if UI can show side panel and screen at same time.
|
/// Check if ui can show side panel and screen at same time.
|
||||||
pub fn is_dual_panel_mode(frame: &mut eframe::Frame) -> bool {
|
pub fn is_dual_panel_mode(frame: &mut eframe::Frame) -> bool {
|
||||||
let w = frame.info().window_info.size.x;
|
let w = frame.info().window_info.size.x;
|
||||||
let h = frame.info().window_info.size.y;
|
let h = frame.info().window_info.size.y;
|
||||||
|
|
|
@ -25,7 +25,6 @@ use grin_core::global::ChainTypes;
|
||||||
use grin_servers::{Server, ServerStats};
|
use grin_servers::{Server, ServerStats};
|
||||||
use jni::sys::{jboolean, jstring};
|
use jni::sys::{jboolean, jstring};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use log::info;
|
|
||||||
|
|
||||||
use crate::Settings;
|
use crate::Settings;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue