network + ui: stratum settings setup and list ui, pass platform callbacks to network tabs, add horizontal line view
This commit is contained in:
parent
7dba27e6d1
commit
4ad134c5e3
10 changed files with 249 additions and 140 deletions
|
@ -12,10 +12,10 @@ network:
|
|||
autorun: Autorun
|
||||
disabled_server: 'Enable integrated node or choose another connection method by pressing %{dots} in the top-left corner of the screen.'
|
||||
sync_status:
|
||||
server_restarting: Server is restarting
|
||||
server_down: Server is down
|
||||
initial: Server is starting
|
||||
no_sync: Server is running
|
||||
node_restarting: Node is restarting
|
||||
node_down: Node is down
|
||||
initial: Node is starting
|
||||
no_sync: Node is running
|
||||
awaiting_peers: Waiting for peers
|
||||
header_sync: Downloading headers
|
||||
header_sync_percent: 'Downloading headers: %{percent}%'
|
||||
|
@ -31,7 +31,7 @@ sync_status:
|
|||
tx_hashset_save: Finalizing chain state
|
||||
body_sync: Downloading blocks
|
||||
body_sync_percent: 'Downloading blocks: %{percent}%'
|
||||
shutdown: Server is shutting down
|
||||
shutdown: Node is shutting down
|
||||
network_node:
|
||||
header: Header
|
||||
block: Block
|
||||
|
@ -55,11 +55,15 @@ network_metrics:
|
|||
difficulty_window: 'Difficulty window %{size}'
|
||||
network_mining:
|
||||
loading: Mining will be available after the synchronization
|
||||
server_setup: Stratum server setup
|
||||
enable_server: Enable server
|
||||
disabled_server: 'Enable stratum server at %{address} or change settings by selecting %{settings} at the bottom of the screen.'
|
||||
server_setting: 'Enable stratum server or change more settings by selecting %{settings} at the bottom of the screen.'
|
||||
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.'
|
||||
address: IP Address
|
||||
wallet: Wallet Address
|
||||
no_ip_addresses: There are no available IP addresses on your system, the server cannot be started, check your network connectivity.
|
||||
choose_ip_address: 'Choose IP Address:'
|
||||
change_port: 'Change port:'
|
||||
ip_address: IP Address
|
||||
rewards_wallet: Wallet for rewards
|
||||
server: Stratum server
|
||||
miners: Miners
|
||||
devices: Devices
|
||||
|
|
|
@ -12,10 +12,10 @@ network:
|
|||
autorun: Автозапуск
|
||||
disabled_server: 'Включите встроенный узел или выберите другой способ подключения, нажав %{dots} в левом-верхнем углу экрана.'
|
||||
sync_status:
|
||||
server_restarting: Сервер перезапускается
|
||||
server_down: Сервер выключен
|
||||
initial: Запуск сервера
|
||||
no_sync: Сервер запущен
|
||||
node_restarting: Узел перезапускается
|
||||
node_down: Узел выключен
|
||||
initial: Запуск узла
|
||||
no_sync: Узел запущен
|
||||
awaiting_peers: Ожидание пиров
|
||||
header_sync: Загрузка заголовков
|
||||
header_sync_percent: 'Загрузка заголовков: %{percent}%'
|
||||
|
@ -31,7 +31,7 @@ sync_status:
|
|||
tx_hashset_save: Сохранение состояния цепи
|
||||
body_sync: Загрузка блоков
|
||||
body_sync_percent: 'Загрузка блоков: %{percent}%'
|
||||
shutdown: Выключение сервера
|
||||
shutdown: Выключение узла
|
||||
network_node:
|
||||
header: Заголовок
|
||||
block: Блок
|
||||
|
@ -55,11 +55,15 @@ network_metrics:
|
|||
difficulty_window: 'Окно сложности %{size}'
|
||||
network_mining:
|
||||
loading: Майнинг будет доступен после синхронизации
|
||||
server_setup: Настройка stratum-сервера
|
||||
enable_server: Включить сервер
|
||||
disabled_server: 'Включите stratum-сервер по адресу %{address} или измените настройки, выбрав %{settings} внизу экрана.'
|
||||
server_setting: 'Включите stratum-сервер или измените больше настроек, выбрав %{settings} внизу экрана.'
|
||||
info: 'Сервер майнинга запущен, вы можете изменить настройки, выбрав %{settings} внизу экрана. Данные обновляются, когда устройства подключены.'
|
||||
address: IP Адрес
|
||||
wallet: Адрес кошелька
|
||||
no_ip_addresses: В вашей системе отсутствуют доступные IP адреса, запуск сервера невозможен, проверьте ваше подключение к сети.
|
||||
choose_ip_address: 'Выберите IP адрес:'
|
||||
change_port: 'Измените порт:'
|
||||
ip_address: IP Адрес
|
||||
rewards_wallet: Кошелёк для наград
|
||||
server: Stratum-сервер
|
||||
miners: Майнеры
|
||||
devices: Устройства
|
||||
|
|
|
@ -64,7 +64,7 @@ impl Modal {
|
|||
/// Default width of the content.
|
||||
const DEFAULT_WIDTH: i64 = 380;
|
||||
|
||||
/// Create open and closeable [`Modal`] with center position.
|
||||
/// Create open and closeable Modal with center position.
|
||||
pub fn new(id: ModalId, location: ModalLocation) -> Self {
|
||||
Self {
|
||||
id,
|
||||
|
@ -76,45 +76,45 @@ impl Modal {
|
|||
}
|
||||
}
|
||||
|
||||
/// Setup position of [`Modal`] on the screen.
|
||||
/// Setup position of Modal on the screen.
|
||||
pub fn position(mut self, position: ModalPosition) -> Self {
|
||||
self.position = position;
|
||||
self
|
||||
}
|
||||
|
||||
/// Check if [`Modal`] is open.
|
||||
/// Check if Modal is open.
|
||||
pub fn is_open(&self) -> bool {
|
||||
self.open.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Mark [`Modal`] closed.
|
||||
/// Mark Modal closed.
|
||||
pub fn close(&self) {
|
||||
self.open.store(false, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Setup possibility to close [`Modal`].
|
||||
/// Setup possibility to close Modal.
|
||||
pub fn closeable(self, closeable: bool) -> Self {
|
||||
self.closeable.store(closeable, Ordering::Relaxed);
|
||||
self
|
||||
}
|
||||
|
||||
/// Disable possibility to close [`Modal`].
|
||||
/// Disable possibility to close Modal.
|
||||
pub fn disable_closing(&self) {
|
||||
self.closeable.store(false, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Check if [`Modal`] is closeable.
|
||||
/// Check if Modal is closeable.
|
||||
pub fn is_closeable(&self) -> bool {
|
||||
self.closeable.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Set title text.
|
||||
/// Set title text on Modal creation.
|
||||
pub fn title(mut self, title: String) -> Self {
|
||||
self.title = Some(title.to_uppercase());
|
||||
self
|
||||
}
|
||||
|
||||
/// 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)) {
|
||||
let width = min(ui.available_width() as i64 - 20, Self::DEFAULT_WIDTH) as f32;
|
||||
|
||||
|
@ -252,11 +252,6 @@ impl Modal {
|
|||
ui.painter().set(bg_idx, bg_shape);
|
||||
|
||||
// Draw line below title.
|
||||
let line_size = Vec2::new(ui.available_width(), 1.0);
|
||||
let (line_rect, _) = ui.allocate_exact_size(line_size, Sense::hover());
|
||||
let painter = ui.painter();
|
||||
painter.hline(line_rect.x_range(),
|
||||
painter.round_to_pixel(line_rect.center().y),
|
||||
View::DEFAULT_STROKE);
|
||||
View::horizontal_line(ui, Colors::STROKE);
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ use crate::Settings;
|
|||
|
||||
pub trait NetworkTab {
|
||||
fn get_type(&self) -> NetworkTabType;
|
||||
fn ui(&mut self, ui: &mut egui::Ui);
|
||||
fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks);
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
|
@ -67,7 +67,7 @@ impl Default for Network {
|
|||
}
|
||||
|
||||
impl Network {
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, _: &dyn PlatformCallbacks) {
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
|
||||
egui::TopBottomPanel::top("network_title")
|
||||
.resizable(false)
|
||||
.frame(egui::Frame {
|
||||
|
@ -98,7 +98,7 @@ impl Network {
|
|||
.. Default::default()
|
||||
})
|
||||
.show_inside(ui, |ui| {
|
||||
self.current_tab.ui(ui);
|
||||
self.current_tab.ui(ui, cb);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ use grin_servers::DiffBlock;
|
|||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{AT, COINS, CUBE_TRANSPARENT, HASH, HOURGLASS_LOW, HOURGLASS_MEDIUM, TIMER};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::node::Node;
|
||||
|
||||
|
@ -33,7 +34,7 @@ impl NetworkTab for NetworkMetrics {
|
|||
NetworkTabType::Metrics
|
||||
}
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
|
||||
let server_stats = Node::get_stats();
|
||||
// Show message when node is not running or loading spinner when metrics are not available.
|
||||
if server_stats.is_none() || server_stats.as_ref().unwrap().diff_stats.height == 0 {
|
||||
|
|
|
@ -12,13 +12,18 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::fmt::format;
|
||||
use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use egui::{RichText, Rounding, ScrollArea, Stroke};
|
||||
use grin_chain::SyncStatus;
|
||||
use grin_servers::WorkerStats;
|
||||
use pnet::ipnetwork::IpNetwork;
|
||||
|
||||
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, WRENCH};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::node::Node;
|
||||
use crate::Settings;
|
||||
|
@ -31,8 +36,9 @@ impl NetworkTab for NetworkMining {
|
|||
NetworkTabType::Mining
|
||||
}
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
|
||||
let server_stats = Node::get_stats();
|
||||
|
||||
// Show message when node is not running or loading spinner when mining are not available.
|
||||
if !server_stats.is_some() || Node::get_sync_status().unwrap() != SyncStatus::NoSync {
|
||||
if !Node::is_running() {
|
||||
|
@ -50,63 +56,158 @@ impl NetworkTab for NetworkMining {
|
|||
return;
|
||||
}
|
||||
|
||||
// Stratum mining server address.
|
||||
let stratum_address = Settings::node_config_to_read()
|
||||
let stratum_stats = &server_stats.as_ref().unwrap().stratum_stats;
|
||||
|
||||
// Stratum server address + port from config.
|
||||
let saved_stratum_addr = Settings::node_config_to_read()
|
||||
.members.clone()
|
||||
.server.stratum_mining_config.unwrap()
|
||||
.stratum_server_addr.unwrap();
|
||||
let (stratum_addr, stratum_port) = saved_stratum_addr.split_once(":").unwrap();
|
||||
|
||||
let stratum_stats = &server_stats.as_ref().unwrap().stratum_stats;
|
||||
if !stratum_stats.is_running && !Node::is_stratum_server_starting() {
|
||||
// Show Stratum setup when mining server is not enabled.
|
||||
View::center_content(ui, 162.0, |ui| {
|
||||
let text = t!(
|
||||
"network_mining.disabled_server",
|
||||
"address" => stratum_address,
|
||||
"settings" => FADERS
|
||||
);
|
||||
ui.label(RichText::new(text)
|
||||
// List of available ip addresses.
|
||||
let mut addresses = Vec::new();
|
||||
for net_if in pnet::datalink::interfaces() {
|
||||
for ip in net_if.ips {
|
||||
if ip.is_ipv4() {
|
||||
addresses.push(ip.ip());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show error message when IP addresses are not available on the system.
|
||||
if addresses.is_empty() {
|
||||
View::center_content(ui, 52.0, |ui| {
|
||||
ui.label(RichText::new(t!("network_mining.no_ip_addresses"))
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
|
||||
let mut addresses = Vec::new();
|
||||
for net_if in pnet::datalink::interfaces() {
|
||||
for ip in net_if.ips {
|
||||
if ip.is_ipv4() {
|
||||
addresses.push(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
if addresses.len() != 0 {
|
||||
|
||||
}
|
||||
|
||||
ui.add_space(10.0);
|
||||
|
||||
View::button(ui, t!("network_mining.enable_server"), Colors::GOLD, || {
|
||||
Node::start_stratum_server();
|
||||
});
|
||||
|
||||
ui.add_space(2.0);
|
||||
|
||||
// Check if stratum server is enabled at config.
|
||||
let stratum_enabled = Settings::node_config_to_read()
|
||||
.members.clone()
|
||||
.server.stratum_mining_config.unwrap()
|
||||
.enable_stratum_server.unwrap();
|
||||
|
||||
View::checkbox(ui, stratum_enabled, t!("network.autorun"), || {
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members
|
||||
.server.stratum_mining_config.as_mut().unwrap()
|
||||
.enable_stratum_server = Some(!stratum_enabled);
|
||||
w_node_config.save();
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Show stratum server setup when mining server is not enabled.
|
||||
if !stratum_stats.is_running && !Node::is_stratum_server_starting() {
|
||||
ScrollArea::vertical()
|
||||
.auto_shrink([false; 2])
|
||||
.show(ui, |ui| {
|
||||
ui.add_space(6.0);
|
||||
View::sub_title(ui,
|
||||
format!("{} {}", WRENCH, t!("network_mining.server_setup")));
|
||||
|
||||
ui.add_space(4.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_mining.choose_ip_address"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
ui.add_space(10.0);
|
||||
|
||||
if addresses.len() != 0 {
|
||||
let saved_ip_addr = &IpAddr::from_str(stratum_addr).unwrap();
|
||||
let mut selected_addr = saved_ip_addr;
|
||||
|
||||
// Set first IP address as current if saved is not present at system.
|
||||
if !addresses.contains(selected_addr) {
|
||||
selected_addr = addresses.get(0).unwrap();
|
||||
}
|
||||
|
||||
// Show available IP addresses on the system.
|
||||
let _ = addresses.chunks(2).map(|x| {
|
||||
if x.len() == 2 {
|
||||
ui.columns(2, |columns| {
|
||||
let addr0 = x.get(0).unwrap();
|
||||
columns[0].vertical_centered(|ui| {
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr0,
|
||||
addr0.to_string());
|
||||
});
|
||||
let addr1 = x.get(1).unwrap();
|
||||
columns[1].vertical_centered(|ui| {
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr1,
|
||||
addr1.to_string());
|
||||
})
|
||||
});
|
||||
ui.add_space(12.0);
|
||||
} else {
|
||||
let addr = x.get(0).unwrap();
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr,
|
||||
addr.to_string());
|
||||
ui.add_space(4.0);
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// Save stratum server address at config if it was changed.
|
||||
if saved_ip_addr != selected_addr {
|
||||
let addr_to_save = format!("{}:{}", selected_addr, stratum_port);
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members
|
||||
.server.stratum_mining_config.as_mut().unwrap()
|
||||
.stratum_server_addr = Some(addr_to_save);
|
||||
w_node_config.save();
|
||||
}
|
||||
}
|
||||
|
||||
ui.label(RichText::new(t!("network_mining.change_port"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
|
||||
// Show button to choose server port.
|
||||
ui.add_space(6.0);
|
||||
View::button(ui, stratum_port.to_string(), Colors::WHITE, || {
|
||||
//TODO: Open modal to change value
|
||||
cb.show_keyboard();
|
||||
});
|
||||
|
||||
ui.add_space(14.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Show message about stratum server config.
|
||||
let text = t!(
|
||||
"network_mining.server_setting",
|
||||
"address" => saved_stratum_addr,
|
||||
"settings" => FADERS
|
||||
);
|
||||
ui.label(RichText::new(text)
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Show button to enable server.
|
||||
View::button(ui, t!("network_mining.enable_server"), Colors::GOLD, || {
|
||||
Node::start_stratum_server();
|
||||
});
|
||||
ui.add_space(2.0);
|
||||
|
||||
let stratum_enabled = Settings::node_config_to_read()
|
||||
.members.clone()
|
||||
.server.stratum_mining_config.unwrap()
|
||||
.enable_stratum_server.unwrap();
|
||||
|
||||
// Show stratum server autorun checkbox.
|
||||
View::checkbox(ui, stratum_enabled, t!("network.autorun"), || {
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members
|
||||
.server.stratum_mining_config.as_mut().unwrap()
|
||||
.enable_stratum_server = Some(!stratum_enabled);
|
||||
w_node_config.save();
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
return;
|
||||
} else if Node::is_stratum_server_starting() {
|
||||
// Show loading spinner when mining server is starting.
|
||||
ui.centered_and_justified(|ui| {
|
||||
View::big_loading_spinner(ui);
|
||||
});
|
||||
|
@ -118,8 +219,8 @@ impl NetworkTab for NetworkMining {
|
|||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered(|ui| {
|
||||
View::rounded_box(ui,
|
||||
stratum_address,
|
||||
t!("network_mining.address"),
|
||||
saved_stratum_addr,
|
||||
t!("network_mining.ip_address"),
|
||||
[true, false, true, false]);
|
||||
});
|
||||
columns[1].vertical_centered(|ui| {
|
||||
|
@ -131,7 +232,7 @@ impl NetworkTab for NetworkMining {
|
|||
.replace("http://", "");
|
||||
View::rounded_box(ui,
|
||||
wallet_address,
|
||||
t!("network_mining.wallet"),
|
||||
t!("network_mining.rewards_wallet"),
|
||||
[false, true, false, true]);
|
||||
});
|
||||
});
|
||||
|
@ -198,6 +299,10 @@ impl NetworkTab for NetworkMining {
|
|||
// Show workers stats or info text when possible.
|
||||
let workers_size = stratum_stats.worker_stats.len();
|
||||
if workers_size != 0 && stratum_stats.num_workers > 0 {
|
||||
ui.add_space(4.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(4.0);
|
||||
|
||||
ScrollArea::vertical()
|
||||
.auto_shrink([false; 2])
|
||||
.id_source("stratum_workers_scroll")
|
||||
|
@ -240,9 +345,8 @@ fn draw_worker_stats(ui: &mut egui::Ui, ws: &WorkerStats, rounding: [bool; 2]) {
|
|||
ui.add_space(4.0);
|
||||
}
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
ui.vertical_centered_justified(|ui| {
|
||||
let mut rect = ui.available_rect_before_wrap();
|
||||
rect.set_height(WORKER_UI_HEIGHT);
|
||||
ui.painter().rect(
|
||||
|
@ -259,25 +363,25 @@ fn draw_worker_stats(ui: &mut egui::Ui, ws: &WorkerStats, rounding: [bool; 2]) {
|
|||
|
||||
ui.add_space(2.0);
|
||||
ui.horizontal_top(|ui| {
|
||||
let (status_text, status_icon) = match ws.is_connected {
|
||||
true => { (t!("network_mining.connected"), PLUGS_CONNECTED) }
|
||||
false => { (t!("network_mining.disconnected"), PLUGS) }
|
||||
let (status_text, status_icon, status_color) = match ws.is_connected {
|
||||
true => { (t!("network_mining.connected"), PLUGS_CONNECTED, Colors::BLACK) }
|
||||
false => { (t!("network_mining.disconnected"), PLUGS, Colors::INACTIVE_TEXT) }
|
||||
};
|
||||
ui.add_space(5.0);
|
||||
ui.heading(RichText::new(status_icon)
|
||||
.color(Colors::BLACK)
|
||||
.color(status_color)
|
||||
.size(18.0));
|
||||
ui.add_space(2.0);
|
||||
|
||||
// Draw worker ID.
|
||||
ui.heading(RichText::new(&ws.id)
|
||||
.color(Colors::BLACK)
|
||||
.color(status_color)
|
||||
.size(18.0));
|
||||
ui.add_space(3.0);
|
||||
|
||||
// Draw worker status.
|
||||
ui.heading(RichText::new(status_text)
|
||||
.color(Colors::BLACK)
|
||||
.color(status_color)
|
||||
.size(18.0));
|
||||
});
|
||||
ui.horizontal_top(|ui| {
|
||||
|
@ -347,7 +451,6 @@ fn draw_worker_stats(ui: &mut egui::Ui, ws: &WorkerStats, rounding: [bool; 2]) {
|
|||
.size(16.0));
|
||||
|
||||
});
|
||||
ui.add_space(2.0);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -18,6 +18,7 @@ use grin_servers::PeerStats;
|
|||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{AT, CUBE, DEVICES, FLOW_ARROW, HANDSHAKE, PACKAGE, PLUGS_CONNECTED, SHARE_NETWORK};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::node::Node;
|
||||
|
||||
|
@ -29,7 +30,7 @@ impl NetworkTab for NetworkNode {
|
|||
NetworkTabType::Node
|
||||
}
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
|
||||
let server_stats = Node::get_stats();
|
||||
// Show message when node is not running or loading spinner when stats are not available.
|
||||
if !server_stats.is_some() {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
use grin_core::global::ChainTypes;
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{NetworkTab, NetworkTabType};
|
||||
use crate::Settings;
|
||||
|
||||
|
@ -24,6 +25,6 @@ impl NetworkTab for NetworkSettings {
|
|||
NetworkTabType::Settings
|
||||
}
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
|
||||
}
|
||||
}
|
|
@ -12,13 +12,13 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use egui::{Button, PointerState, Response, RichText, Sense, Spinner, Widget};
|
||||
use egui::{AboveOrBelow, Button, PointerState, Response, RichText, ScrollArea, Sense, Spinner, Widget, WidgetText};
|
||||
use egui::epaint::{Color32, FontId, RectShape, Rounding, Stroke};
|
||||
use egui::epaint::text::TextWrapping;
|
||||
use egui::text::{LayoutJob, TextFormat};
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{CHECK_SQUARE, CIRCLE, RADIO_BUTTON, SQUARE};
|
||||
use crate::gui::icons::{CARET_DOWN, CHECK_SQUARE, CIRCLE, RADIO_BUTTON, SQUARE};
|
||||
|
||||
pub struct View;
|
||||
|
||||
|
@ -62,17 +62,17 @@ impl View {
|
|||
ui.add_space(4.0);
|
||||
}
|
||||
|
||||
/// Temporary button click optimization for touch screens.
|
||||
fn on_button_click(ui: &mut egui::Ui, resp: Response, action: impl FnOnce()) {
|
||||
/// Temporary click optimization for touch screens, return `true` if it was clicked.
|
||||
fn touched(ui: &mut egui::Ui, resp: Response) -> bool {
|
||||
let drag_resp = resp.interact(Sense::click_and_drag());
|
||||
// Clear pointer event if dragging is out of button area
|
||||
if drag_resp.dragged() && !ui.rect_contains_pointer(drag_resp.rect) {
|
||||
ui.input_mut().pointer = PointerState::default();
|
||||
}
|
||||
// Call click action if button is clicked or drag released
|
||||
if drag_resp.drag_released() || drag_resp.clicked() {
|
||||
(action)();
|
||||
};
|
||||
return true
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Title button with transparent background fill color, contains only icon.
|
||||
|
@ -80,13 +80,13 @@ impl View {
|
|||
ui.scope(|ui| {
|
||||
// Disable stroke around title buttons on hover
|
||||
ui.style_mut().visuals.widgets.active.bg_stroke = Stroke::NONE;
|
||||
|
||||
let wt = RichText::new(icon.to_string()).size(24.0).color(Colors::TITLE);
|
||||
let br = Button::new(wt)
|
||||
.fill(Colors::TRANSPARENT)
|
||||
.ui(ui);
|
||||
|
||||
Self::on_button_click(ui, br, action);
|
||||
if Self::touched(ui, br) {
|
||||
(action)();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -96,34 +96,32 @@ impl View {
|
|||
true => { Colors::TITLE }
|
||||
false => { Colors::TEXT }
|
||||
};
|
||||
let wt = RichText::new(icon.to_string()).size(24.0).color(text_color);
|
||||
|
||||
let stroke = match active {
|
||||
true => { Stroke::NONE }
|
||||
false => { Self::DEFAULT_STROKE }
|
||||
};
|
||||
|
||||
let color = match active {
|
||||
true => { Colors::FILL }
|
||||
false => { Colors::WHITE }
|
||||
};
|
||||
let br = Button::new(wt)
|
||||
let br = Button::new(RichText::new(icon.to_string()).size(24.0).color(text_color))
|
||||
.stroke(stroke)
|
||||
.fill(color)
|
||||
.ui(ui);
|
||||
|
||||
Self::on_button_click(ui, br, action);
|
||||
if Self::touched(ui, br) {
|
||||
(action)();
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw [`Button`] with specified background fill color.
|
||||
pub fn button(ui: &mut egui::Ui, text: String, fill_color: Color32, action: impl FnOnce()) {
|
||||
let wt = RichText::new(text.to_uppercase()).size(18.0).color(Colors::BUTTON);
|
||||
let br = Button::new(wt)
|
||||
let br = Button::new(RichText::new(text.to_uppercase()).size(18.0).color(Colors::BUTTON))
|
||||
.stroke(Self::DEFAULT_STROKE)
|
||||
.fill(fill_color)
|
||||
.ui(ui);
|
||||
|
||||
Self::on_button_click(ui, br, action);
|
||||
if Self::touched(ui, br) {
|
||||
(action)();
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw rounded box with some value and label in the middle,
|
||||
|
@ -212,31 +210,33 @@ impl View {
|
|||
true => { (format!("{} {}", CHECK_SQUARE, text), Colors::BUTTON) }
|
||||
false => { (format!("{} {}", SQUARE, text), Colors::TEXT) }
|
||||
};
|
||||
|
||||
let wt = RichText::new(text_value).size(18.0).color(color);
|
||||
let br = Button::new(wt)
|
||||
let br = Button::new(RichText::new(text_value).size(18.0).color(color))
|
||||
.frame(false)
|
||||
.stroke(Stroke::NONE)
|
||||
.fill(Colors::TRANSPARENT)
|
||||
.ui(ui);
|
||||
|
||||
Self::on_button_click(ui, br, callback);
|
||||
if Self::touched(ui, br) {
|
||||
(callback)();
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw the radio button with callback on select.
|
||||
pub fn radio_button(ui: &mut egui::Ui, selected: bool, text: String, callback: impl FnOnce()) {
|
||||
let (text_value, color) = match selected {
|
||||
true => { (format!("{} {}", RADIO_BUTTON, text), Colors::BUTTON) }
|
||||
false => { (format!("{} {}", CIRCLE, text), Colors::TEXT) }
|
||||
};
|
||||
/// Show a [`RadioButton`]. It is selected if `*current_value == selected_value`.
|
||||
/// If clicked, `selected_value` is assigned to `*current_value`.
|
||||
pub fn radio_value<T: PartialEq>(ui: &mut egui::Ui, current: &mut T, value: T, text: String) {
|
||||
let mut response = ui.radio(*current == value, text);
|
||||
if Self::touched(ui, response.clone()) && *current != value {
|
||||
*current = value;
|
||||
response.mark_changed();
|
||||
}
|
||||
}
|
||||
|
||||
let wt = RichText::new(text_value).size(18.0).color(color);
|
||||
let br = Button::new(wt)
|
||||
.frame(false)
|
||||
.stroke(Stroke::NONE)
|
||||
.fill(Colors::TRANSPARENT)
|
||||
.ui(ui);
|
||||
|
||||
Self::on_button_click(ui, br, callback);
|
||||
/// Draw horizontal line
|
||||
pub fn horizontal_line(ui: &mut egui::Ui, color: Color32) {
|
||||
let line_size = egui::Vec2::new(ui.available_width(), 1.0);
|
||||
let (line_rect, _) = ui.allocate_exact_size(line_size, Sense::hover());
|
||||
let painter = ui.painter();
|
||||
painter.hline(line_rect.x_range(),
|
||||
painter.round_to_pixel(line_rect.center().y),
|
||||
Stroke { width: 1.0, color });
|
||||
}
|
||||
}
|
|
@ -221,13 +221,13 @@ impl Node {
|
|||
};
|
||||
|
||||
if Node::is_restarting() {
|
||||
return t!("sync_status.server_restarting")
|
||||
return t!("sync_status.node_restarting")
|
||||
}
|
||||
|
||||
let sync_status = Self::get_sync_status();
|
||||
|
||||
if sync_status.is_none() {
|
||||
return t!("sync_status.server_down")
|
||||
return t!("sync_status.node_down")
|
||||
}
|
||||
|
||||
match sync_status.unwrap() {
|
||||
|
|
Loading…
Reference in a new issue