ui: refactor colors, add disabled server message, optimize Android sensor delay.

This commit is contained in:
ardocrat 2023-06-03 11:22:51 +03:00
parent de7be791a9
commit c4a87ad755
15 changed files with 158 additions and 174 deletions

View file

@ -5,7 +5,6 @@ import android.os.Bundle;
import android.os.Process; import android.os.Process;
import android.system.ErrnoException; import android.system.ErrnoException;
import android.system.Os; import android.system.Os;
import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.OrientationEventListener; import android.view.OrientationEventListener;
import com.google.androidgamesdk.GameActivity; import com.google.androidgamesdk.GameActivity;
@ -30,7 +29,7 @@ public class MainActivity extends GameActivity {
// Callback to update display cutouts at native code. // Callback to update display cutouts at native code.
OrientationEventListener orientationEventListener = new OrientationEventListener(this, OrientationEventListener orientationEventListener = new OrientationEventListener(this,
SensorManager.SENSOR_DELAY_FASTEST) { SensorManager.SENSOR_DELAY_NORMAL) {
@Override @Override
public void onOrientationChanged(int orientation) { public void onOrientationChanged(int orientation) {
onDisplayCutoutsChanged(Utils.getDisplayCutouts(MainActivity.this)); onDisplayCutoutsChanged(Utils.getDisplayCutouts(MainActivity.this));
@ -83,7 +82,6 @@ public class MainActivity extends GameActivity {
// Called from native code // Called from native code
public void onExit() { public void onExit() {
Log.d("12345", "onExit");
mManualExit = true; mManualExit = true;
BackgroundService.stop(this); BackgroundService.stop(this);
finish(); finish();

View file

@ -8,6 +8,7 @@ network:
enable: Enable enable: Enable
disable: Disable disable: Disable
restart: Restart restart: Restart
inactive_message: 'Enable server or choose/add another connection method by pressing %{dots} on top left corner of the screen.'
sync_status: sync_status:
server_restarting: Server is restarting server_restarting: Server is restarting
server_down: Server is down server_down: Server is down
@ -22,7 +23,7 @@ sync_status:
tx_hashset_range_proofs_validation: 'Validating state - range proofs: %{percent}%' tx_hashset_range_proofs_validation: 'Validating state - range proofs: %{percent}%'
tx_hashset_kernels_validation: 'Validating state - kernels: %{percent}%' tx_hashset_kernels_validation: 'Validating state - kernels: %{percent}%'
tx_hashset_save: Finalizing chain state tx_hashset_save: Finalizing chain state
body_sync: Downloading blocks body_sync: Downloading blockchain
body_sync_percent: 'Downloading blocks: %{percent}%' body_sync_percent: 'Downloading blocks: %{percent}%'
shutdown: Server is shutting down shutdown: Server is shutting down
network_node: network_node:

View file

@ -8,6 +8,7 @@ network:
enable: Включить enable: Включить
disable: Выключить disable: Выключить
restart: Перезапустить restart: Перезапустить
inactive_message: 'Включите сервер или выберите/добавьте другой способ подключения, нажав %{dots} в левом верхнем углу экрана.'
sync_status: sync_status:
server_restarting: Сервер перезапускается server_restarting: Сервер перезапускается
server_down: Сервер выключен server_down: Сервер выключен
@ -22,7 +23,7 @@ sync_status:
tx_hashset_range_proofs_validation: 'Проверка доказательств: %{percent}%' tx_hashset_range_proofs_validation: 'Проверка доказательств: %{percent}%'
tx_hashset_kernels_validation: 'Проверка ядер: %{percent}%' tx_hashset_kernels_validation: 'Проверка ядер: %{percent}%'
tx_hashset_save: Сохранение состояния цепи tx_hashset_save: Сохранение состояния цепи
body_sync: Загрузка блоков body_sync: Загрузка блокчейна
body_sync_percent: 'Загрузка блоков: %{percent}%' body_sync_percent: 'Загрузка блоков: %{percent}%'
shutdown: Выключение сервера shutdown: Выключение сервера
network_node: network_node:

View file

@ -16,8 +16,7 @@ use egui::{Color32, Context, RichText, Spinner, Stroke, Widget};
use egui::os::OperatingSystem; use egui::os::OperatingSystem;
use egui::style::Margin; use egui::style::Margin;
use crate::gui::colors::{COLOR_DARK, COLOR_LIGHT, COLOR_YELLOW}; use crate::gui::{Colors, Navigator};
use crate::gui::Navigator;
use crate::gui::platform::PlatformCallbacks; use crate::gui::platform::PlatformCallbacks;
use crate::gui::screens::Root; use crate::gui::screens::Root;
use crate::gui::views::{Modal, ModalId, ModalLocation, View}; use crate::gui::views::{Modal, ModalId, ModalLocation, View};
@ -38,7 +37,7 @@ impl App {
pub fn ui(&mut self, ctx: &Context, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) { pub fn ui(&mut self, ctx: &Context, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
egui::CentralPanel::default() egui::CentralPanel::default()
.frame(egui::Frame { .frame(egui::Frame {
fill: COLOR_LIGHT, fill: Colors::FILL,
.. Default::default() .. Default::default()
}) })
.show(ctx, |ui| { .show(ctx, |ui| {
@ -64,11 +63,11 @@ impl App {
} }
ui.add_space(16.0); ui.add_space(16.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
Spinner::new().size(42.0).color(COLOR_YELLOW).ui(ui); Spinner::new().size(42.0).color(Colors::GRAY).ui(ui);
ui.add_space(10.0); ui.add_space(10.0);
ui.label(RichText::new(Node::get_sync_status_text()) ui.label(RichText::new(Node::get_sync_status_text())
.size(18.0) .size(18.0)
.color(COLOR_DARK) .color(Colors::INACTIVE_TEXT)
); );
}); });
ui.add_space(12.0); ui.add_space(12.0);
@ -82,7 +81,7 @@ impl App {
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0); ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0);
ui.columns(2, |columns| { ui.columns(2, |columns| {
columns[0].vertical_centered_justified(|ui| { columns[0].vertical_centered_justified(|ui| {
View::button(ui, t!("modal_exit.exit"), Color32::WHITE, || { View::button(ui, t!("modal_exit.exit"), Colors::WHITE, || {
if !Node::is_running() { if !Node::is_running() {
Self::exit(frame, cb); Self::exit(frame, cb);
modal.close(); modal.close();
@ -94,7 +93,7 @@ impl App {
}); });
}); });
columns[1].vertical_centered_justified(|ui| { columns[1].vertical_centered_justified(|ui| {
View::button(ui, t!("modal.cancel"), Color32::WHITE, || { View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
modal.close(); modal.close();
}); });
}); });

View file

@ -12,9 +12,23 @@
// 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.
pub const COLOR_YELLOW: egui::Color32 = egui::Color32::from_rgb(254, 241, 2); use egui::Color32;
pub const COLOR_LIGHT: egui::Color32 = egui::Color32::from_gray(240);
pub const COLOR_DARK: egui::Color32 = egui::Color32::from_gray(60); pub struct Colors;
pub const COLOR_GRAY: egui::Color32 = egui::Color32::from_gray(120);
pub const COLOR_GRAY_LIGHT: egui::Color32 = egui::Color32::from_gray(220); impl Colors {
pub const COLOR_GRAY_DARK: egui::Color32 = egui::Color32::from_gray(80); pub const WHITE: Color32 = Color32::from_gray(253);
pub const BLACK: Color32 = Color32::from_gray(2);
pub const TRANSPARENT: Color32 = Color32::from_rgba_premultiplied(0, 0, 0, 0);
pub const SEMI_TRANSPARENT: Color32 = Color32::from_black_alpha(100);
pub const YELLOW: Color32 = Color32::from_rgb(254, 241, 2);
pub const GOLD: Color32 = Color32::from_rgb(255, 215, 0);
pub const FILL: Color32 = Color32::from_gray(240);
pub const TITLE: Color32 = Color32::from_gray(60);
pub const SUB_TITLE: Color32 = Color32::from_gray(80);
pub const BUTTON: Color32 = Color32::from_gray(70);
pub const GRAY: Color32 = Color32::from_gray(120);
pub const STROKE: Color32 = Color32::from_gray(190);
pub const INACTIVE_TEXT: Color32 = Color32::from_gray(150);
pub const ITEM_STROKE: Color32 = Color32::from_gray(220);
}

View file

@ -19,8 +19,10 @@ pub use app::{App, PlatformApp};
mod navigator; mod navigator;
pub use navigator::Navigator; pub use navigator::Navigator;
mod colors;
pub use colors::Colors;
pub mod platform; pub mod platform;
pub mod screens; pub mod screens;
pub mod views; pub mod views;
pub mod icons; pub mod icons;
pub mod colors;

View file

@ -20,17 +20,8 @@ use crate::gui::platform::PlatformCallbacks;
use crate::gui::screens::{Screen, ScreenId}; use crate::gui::screens::{Screen, ScreenId};
use crate::gui::views::{TitlePanel, TitlePanelAction, View}; use crate::gui::views::{TitlePanel, TitlePanelAction, View};
pub struct Accounts { #[derive(Default)]
title: String pub struct Accounts;
}
impl Default for Accounts {
fn default() -> Self {
Self {
title: t!("screen_accounts.title").to_uppercase(),
}
}
}
impl Screen for Accounts { impl Screen for Accounts {
fn id(&self) -> ScreenId { fn id(&self) -> ScreenId {
@ -38,9 +29,7 @@ impl Screen for Accounts {
} }
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) { fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
let Self { title } = self; TitlePanel::new(t!("screen_accounts.title"))
TitlePanel::new(title)
.ui(if !View::is_dual_panel_mode(frame) { .ui(if !View::is_dual_panel_mode(frame) {
TitlePanelAction::new(GLOBE, || { TitlePanelAction::new(GLOBE, || {
Navigator::toggle_side_panel(); Navigator::toggle_side_panel();

View file

@ -30,6 +30,6 @@ mod network_metrics;
mod network_mining; mod network_mining;
pub trait NetworkTab { pub trait NetworkTab {
fn name(&self) -> &String; fn name(&self) -> String;
fn ui(&mut self, ui: &mut egui::Ui); fn ui(&mut self, ui: &mut egui::Ui);
} }

View file

@ -15,12 +15,12 @@
use std::cmp::min; use std::cmp::min;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use egui::{Align2, Color32, RichText, Rounding, Sense, Separator, Stroke, Vec2, Widget}; use egui::{Align2, RichText, Rounding, Sense, Separator, Stroke, Vec2, Widget};
use egui::epaint::RectShape; use egui::epaint::RectShape;
use egui::style::Margin; use egui::style::Margin;
use egui_extras::{Size, StripBuilder}; use egui_extras::{Size, StripBuilder};
use crate::gui::Colors;
use crate::gui::colors::{COLOR_DARK, COLOR_LIGHT, COLOR_YELLOW};
use crate::gui::views::View; use crate::gui::views::View;
/// Identifier for [`Modal`] content to draw at [`Modal::ui`]. /// Identifier for [`Modal`] content to draw at [`Modal::ui`].
@ -128,7 +128,7 @@ impl Modal {
.fixed_pos(ui.next_widget_position()) .fixed_pos(ui.next_widget_position())
.fixed_size(ui.available_size()) .fixed_size(ui.available_size())
.frame(egui::Frame { .frame(egui::Frame {
fill: Color32::from_black_alpha(100), fill: Colors::SEMI_TRANSPARENT,
..Default::default() ..Default::default()
}) })
.show(ui.ctx(), |ui| { .show(ui.ctx(), |ui| {
@ -144,7 +144,7 @@ impl Modal {
.anchor(self.modal_position(), Vec2::default()) .anchor(self.modal_position(), Vec2::default())
.frame(egui::Frame { .frame(egui::Frame {
rounding: Rounding::same(8.0), rounding: Rounding::same(8.0),
fill: COLOR_YELLOW, fill: Colors::YELLOW,
..Default::default() ..Default::default()
}) })
.show(ui.ctx(), |ui| { .show(ui.ctx(), |ui| {
@ -202,7 +202,7 @@ impl Modal {
let mut bg_shape = RectShape { let mut bg_shape = RectShape {
rect, rect,
rounding, rounding,
fill: COLOR_LIGHT, fill: Colors::FILL,
stroke: Stroke::NONE, stroke: Stroke::NONE,
}; };
let bg_idx = ui.painter().add(bg_shape); let bg_idx = ui.painter().add(bg_shape);
@ -232,7 +232,7 @@ impl Modal {
sw: 0.0, sw: 0.0,
se: 0.0, se: 0.0,
}, },
fill: COLOR_YELLOW, fill: Colors::YELLOW,
stroke: Stroke::NONE, stroke: Stroke::NONE,
}; };
let bg_idx = ui.painter().add(bg_shape); let bg_idx = ui.painter().add(bg_shape);
@ -241,7 +241,10 @@ impl Modal {
let title_resp = ui.allocate_ui_at_rect(rect, |ui| { let title_resp = ui.allocate_ui_at_rect(rect, |ui| {
ui.vertical_centered_justified(|ui| { ui.vertical_centered_justified(|ui| {
ui.add_space(8.0); ui.add_space(8.0);
ui.label(RichText::new(self.title.as_ref().unwrap()).size(20.0).color(COLOR_DARK)); ui.label(RichText::new(self.title.as_ref().unwrap())
.size(20.0)
.color(Colors::TITLE)
);
ui.add_space(8.0); ui.add_space(8.0);
}); });
}).response; }).response;
@ -250,10 +253,12 @@ impl Modal {
bg_shape.rect = title_resp.rect; bg_shape.rect = title_resp.rect;
ui.painter().set(bg_idx, bg_shape); ui.painter().set(bg_idx, bg_shape);
let (rect, _) = ui.allocate_exact_size(Vec2::new(ui.available_width(), 1.0),Sense::hover()); // 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(); let painter = ui.painter();
painter.hline(rect.x_range(), painter.hline(line_rect.x_range(),
painter.round_to_pixel(rect.center().y), painter.round_to_pixel(line_rect.center().y),
View::DEFAULT_STROKE); View::DEFAULT_STROKE);
} }
} }

View file

@ -20,12 +20,12 @@ use egui_extras::{Size, StripBuilder};
use grin_chain::SyncStatus; use grin_chain::SyncStatus;
use grin_core::global::ChainTypes; use grin_core::global::ChainTypes;
use crate::gui::colors::{COLOR_DARK, COLOR_GRAY, COLOR_GRAY_DARK, COLOR_YELLOW};
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE, PLUGS, POWER}; use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE, PLUGS, POWER};
use crate::gui::Navigator; use crate::gui::{Colors, Navigator};
use crate::gui::platform::PlatformCallbacks; use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{NetworkTab, View}; use crate::gui::views::{NetworkTab, 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_node::NetworkNode; use crate::gui::views::network_node::NetworkNode;
use crate::node::Node; use crate::node::Node;
@ -33,7 +33,7 @@ use crate::node::Node;
enum Mode { enum Mode {
Node, Node,
Metrics, Metrics,
Miner, Mining,
Tuning Tuning
} }
@ -42,6 +42,7 @@ pub struct Network {
node_view: NetworkNode, node_view: NetworkNode,
metrics_view: NetworkMetrics, metrics_view: NetworkMetrics,
mining_view: NetworkMining,
} }
impl Default for Network { impl Default for Network {
@ -49,7 +50,8 @@ impl Default for Network {
Self { Self {
current_mode: Mode::Node, current_mode: Mode::Node,
node_view: NetworkNode::default(), node_view: NetworkNode::default(),
metrics_view: NetworkMetrics::default() metrics_view: NetworkMetrics::default(),
mining_view: NetworkMining::default()
} }
} }
} }
@ -59,7 +61,7 @@ impl Network {
egui::TopBottomPanel::top("network_title") egui::TopBottomPanel::top("network_title")
.resizable(false) .resizable(false)
.frame(egui::Frame { .frame(egui::Frame {
fill: COLOR_YELLOW, fill: Colors::YELLOW,
inner_margin: Margin::same(0.0), inner_margin: Margin::same(0.0),
outer_margin: Margin::same(0.0), outer_margin: Margin::same(0.0),
stroke: Stroke::NONE, stroke: Stroke::NONE,
@ -83,7 +85,7 @@ impl Network {
.frame(egui::Frame { .frame(egui::Frame {
stroke: View::DEFAULT_STROKE, stroke: View::DEFAULT_STROKE,
inner_margin: Margin::same(4.0), inner_margin: Margin::same(4.0),
fill: Color32::WHITE, fill: Colors::WHITE,
.. Default::default() .. Default::default()
}) })
.show_inside(ui, |ui| { .show_inside(ui, |ui| {
@ -110,8 +112,8 @@ impl Network {
}); });
}); });
columns[2].vertical_centered_justified(|ui| { columns[2].vertical_centered_justified(|ui| {
View::tab_button(ui, FACTORY, self.current_mode == Mode::Miner, || { View::tab_button(ui, FACTORY, self.current_mode == Mode::Mining, || {
self.current_mode = Mode::Miner; self.current_mode = Mode::Mining;
}); });
}); });
columns[3].vertical_centered_justified(|ui| { columns[3].vertical_centered_justified(|ui| {
@ -134,7 +136,7 @@ impl Network {
Mode::Tuning => { Mode::Tuning => {
self.node_view.ui(ui); self.node_view.ui(ui);
} }
Mode::Miner => {} Mode::Mining => {}
} }
} }
@ -180,8 +182,8 @@ impl Network {
Mode::Metrics => { Mode::Metrics => {
self.metrics_view.name() self.metrics_view.name()
} }
Mode::Miner => { Mode::Mining => {
self.node_view.name() self.mining_view.name()
} }
Mode::Tuning => { Mode::Tuning => {
self.node_view.name() self.node_view.name()
@ -195,9 +197,9 @@ impl Network {
strip.cell(|ui| { strip.cell(|ui| {
ui.add_space(2.0); ui.add_space(2.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(title_text) ui.label(RichText::new(title_text.to_uppercase())
.size(18.0) .size(18.0)
.color(COLOR_DARK)); .color(Colors::TITLE));
}); });
}); });
strip.cell(|ui| { strip.cell(|ui| {
@ -211,13 +213,13 @@ impl Network {
}; };
let (dark, bright) = (0.3, 1.0); let (dark, bright) = (0.3, 1.0);
let color_factor = if !idle { let color_factor = if !idle {
lerp(dark..=bright, ui.input().time.cos().abs()) lerp(dark..=bright, ui.input().time.cos().abs()) as f32
} else { } else {
bright bright as f32
}; };
// Draw sync text // Draw sync text
let status_color_rgba = Rgba::from(COLOR_GRAY_DARK) * color_factor as f32; let status_color_rgba = Rgba::from(Colors::SUB_TITLE) * color_factor;
let status_color = Color32::from(status_color_rgba); let status_color = Color32::from(status_color_rgba);
View::ellipsize_text(ui, Node::get_sync_status_text(), 15.0, status_color); View::ellipsize_text(ui, Node::get_sync_status_text(), 15.0, status_color);
@ -233,18 +235,16 @@ impl Network {
} }
pub fn server_off_content(ui: &mut egui::Ui) { pub fn server_off_content(ui: &mut egui::Ui) {
View::center_content(ui, [240.0, 214.0], |ui| { View::center_content(ui, [ui.available_width() - 48.0, 160.0], |ui| {
ui.label(RichText::new(PLUGS) let text = t!("network.inactive_message","dots" => DOTS_THREE_OUTLINE_VERTICAL);
.size(84.0) ui.label(RichText::new(text)
.color(Color32::from_gray(200)) .size(16.0)
.color(Colors::INACTIVE_TEXT)
); );
ui.add_space(-16.0);
ui.label(RichText::new(Node::get_sync_status_text()) ui.add_space(10.0);
.size(19.0)
.color(Color32::from_gray(150)) View::button(ui, format!("{} {}", POWER, t!("network.enable")), Colors::GOLD, || {
);
ui.add_space(12.0);
View::button(ui, format!("{} {}", POWER, t!("network.enable")), COLOR_YELLOW, || {
Node::start(ChainTypes::Mainnet); Node::start(ChainTypes::Mainnet);
}); });
}); });

View file

@ -18,30 +18,21 @@ use egui::{RichText, ScrollArea, Spinner, Widget};
use grin_core::global::ChainTypes; use grin_core::global::ChainTypes;
use grin_servers::DiffBlock; use grin_servers::DiffBlock;
use crate::gui::colors::{COLOR_DARK, COLOR_GRAY, COLOR_GRAY_LIGHT, COLOR_YELLOW}; use crate::gui::Colors;
use crate::gui::icons::{AT, COINS, CUBE_TRANSPARENT, HASH, HOURGLASS_LOW, HOURGLASS_MEDIUM, PLUGS, POWER, TIMER}; use crate::gui::icons::{AT, COINS, CUBE_TRANSPARENT, HASH, HOURGLASS_LOW, HOURGLASS_MEDIUM, PLUGS, POWER, TIMER};
use crate::gui::views::{Network, NetworkTab, View}; use crate::gui::views::{Network, NetworkTab, View};
use crate::node::Node; use crate::node::Node;
pub struct NetworkMetrics { #[derive(Default)]
title: String pub struct NetworkMetrics;
}
impl Default for NetworkMetrics {
fn default() -> Self {
Self {
title: t!("network.metrics").to_uppercase(),
}
}
}
const BLOCK_REWARD: f64 = 60.0; const BLOCK_REWARD: f64 = 60.0;
// 1 year is calculated as 365 days and 6 hours (31557600). // 1 year is calculated as 365 days and 6 hours (31557600).
const YEARLY_SUPPLY: f64 = ((60 * 60 * 24 * 365) + 6 * 60 * 60) as f64; const YEARLY_SUPPLY: f64 = ((60 * 60 * 24 * 365) + 6 * 60 * 60) as f64;
impl NetworkTab for NetworkMetrics { impl NetworkTab for NetworkMetrics {
fn name(&self) -> &String { fn name(&self) -> String {
&self.title t!("network.metrics")
} }
fn ui(&mut self, ui: &mut egui::Ui) { fn ui(&mut self, ui: &mut egui::Ui) {
@ -51,11 +42,11 @@ impl NetworkTab for NetworkMetrics {
Network::server_off_content(ui); Network::server_off_content(ui);
} else { } else {
View::center_content(ui, [280.0, 160.0], |ui| { View::center_content(ui, [280.0, 160.0], |ui| {
Spinner::new().size(104.0).color(COLOR_YELLOW).ui(ui); Spinner::new().size(104.0).color(Colors::GOLD).ui(ui);
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(Color32::from_gray(150)) .color(Colors::INACTIVE_TEXT)
); );
}); });
} }
@ -177,60 +168,60 @@ fn draw_diff_block(ui: &mut egui::Ui, db: &DiffBlock, rounding: [bool; 2]) {
se: if rounding[1] { 8.0 } else { 0.0 }, se: if rounding[1] { 8.0 } else { 0.0 },
}, },
Color32::WHITE, Color32::WHITE,
Stroke { width: 1.0, color: COLOR_GRAY_LIGHT } Stroke { width: 1.0, color: Colors::ITEM_STROKE }
); );
ui.add_space(2.0); ui.add_space(2.0);
ui.horizontal_top(|ui| { ui.horizontal_top(|ui| {
ui.add_space(5.0); ui.add_space(5.0);
ui.heading(RichText::new(HASH) ui.heading(RichText::new(HASH)
.color(Color32::BLACK) .color(Colors::BLACK)
.size(18.0)); .size(18.0));
ui.add_space(2.0); ui.add_space(2.0);
// Draw block hash // Draw block hash
ui.heading(RichText::new(db.block_hash.to_string()) ui.heading(RichText::new(db.block_hash.to_string())
.color(Color32::BLACK) .color(Colors::BLACK)
.size(18.0)); .size(18.0));
}); });
ui.horizontal_top(|ui| { ui.horizontal_top(|ui| {
ui.add_space(6.0); ui.add_space(6.0);
ui.heading(RichText::new(CUBE_TRANSPARENT) ui.heading(RichText::new(CUBE_TRANSPARENT)
.color(COLOR_DARK) .color(Colors::TITLE)
.size(16.0)); .size(16.0));
ui.add_space(4.0); ui.add_space(4.0);
// Draw block difficulty and height // Draw block difficulty and height
ui.heading(RichText::new(db.difficulty.to_string()) ui.heading(RichText::new(db.difficulty.to_string())
.color(COLOR_DARK) .color(Colors::TITLE)
.size(16.0)); .size(16.0));
ui.add_space(2.0); ui.add_space(2.0);
ui.heading(RichText::new(AT).color(COLOR_DARK).size(16.0)); ui.heading(RichText::new(AT).color(Colors::TITLE).size(16.0));
ui.add_space(2.0); ui.add_space(2.0);
ui.heading(RichText::new(db.block_height.to_string()) ui.heading(RichText::new(db.block_height.to_string())
.color(COLOR_DARK) .color(Colors::TITLE)
.size(16.0)); .size(16.0));
}); });
ui.horizontal_top(|ui| { ui.horizontal_top(|ui| {
ui.add_space(6.0); ui.add_space(6.0);
ui.heading(RichText::new(TIMER) ui.heading(RichText::new(TIMER)
.color(COLOR_GRAY) .color(Colors::GRAY)
.size(16.0)); .size(16.0));
ui.add_space(4.0); ui.add_space(4.0);
// Draw block time // Draw block time
ui.heading(RichText::new(format!("{}s", db.duration)) ui.heading(RichText::new(format!("{}s", db.duration))
.color(COLOR_GRAY) .color(Colors::GRAY)
.size(16.0)); .size(16.0));
ui.add_space(2.0); ui.add_space(2.0);
ui.heading(RichText::new(HOURGLASS_LOW).color(COLOR_GRAY).size(16.0)); ui.heading(RichText::new(HOURGLASS_LOW).color(Colors::GRAY).size(16.0));
ui.add_space(2.0); ui.add_space(2.0);
let naive_datetime = NaiveDateTime::from_timestamp_opt(db.time as i64, 0); let naive_datetime = NaiveDateTime::from_timestamp_opt(db.time as i64, 0);
if naive_datetime.is_some() { if naive_datetime.is_some() {
let datetime: DateTime<Utc> = DateTime::from_utc(naive_datetime.unwrap(), Utc); let datetime: DateTime<Utc> = DateTime::from_utc(naive_datetime.unwrap(), Utc);
ui.heading(RichText::new(datetime.to_string()) ui.heading(RichText::new(datetime.to_string())
.color(COLOR_GRAY) .color(Colors::GRAY)
.size(16.0)); .size(16.0));
} }
}); });

View file

@ -15,21 +15,12 @@
use egui::Ui; use egui::Ui;
use crate::gui::views::NetworkTab; use crate::gui::views::NetworkTab;
pub struct NetworkMining { #[derive(Default)]
title: String pub struct NetworkMining;
}
impl Default for NetworkMining {
fn default() -> Self {
Self {
title: t!("network.mining").to_uppercase(),
}
}
}
impl NetworkTab for NetworkMining { impl NetworkTab for NetworkMining {
fn name(&self) -> &String { fn name(&self) -> String {
&self.title t!("network.mining")
} }
fn ui(&mut self, ui: &mut Ui) { fn ui(&mut self, ui: &mut Ui) {

View file

@ -17,27 +17,18 @@ use egui::{Color32, RichText, Rounding, ScrollArea, Spinner, Widget};
use egui_extras::{Size, StripBuilder}; use egui_extras::{Size, StripBuilder};
use grin_core::global::ChainTypes; use grin_core::global::ChainTypes;
use grin_servers::PeerStats; use grin_servers::PeerStats;
use crate::gui::Colors;
use crate::gui::colors::{COLOR_DARK, COLOR_GRAY, COLOR_GRAY_LIGHT, COLOR_YELLOW};
use crate::gui::icons::{AT, CUBE, DEVICES, FLOW_ARROW, HANDSHAKE, PACKAGE, PLUGS, PLUGS_CONNECTED, POWER, SHARE_NETWORK}; use crate::gui::icons::{AT, CUBE, DEVICES, FLOW_ARROW, HANDSHAKE, PACKAGE, PLUGS, PLUGS_CONNECTED, POWER, SHARE_NETWORK};
use crate::gui::views::{Network, NetworkTab, View}; use crate::gui::views::{Network, NetworkTab, View};
use crate::node::Node; use crate::node::Node;
pub struct NetworkNode { #[derive(Default)]
title: String pub struct NetworkNode;
}
impl Default for NetworkNode {
fn default() -> Self {
Self {
title: t!("network.node").to_uppercase(),
}
}
}
impl NetworkTab for NetworkNode { impl NetworkTab for NetworkNode {
fn name(&self) -> &String { fn name(&self) -> String {
&self.title t!("network.node")
} }
fn ui(&mut self, ui: &mut egui::Ui) { fn ui(&mut self, ui: &mut egui::Ui) {
@ -47,7 +38,7 @@ impl NetworkTab for NetworkNode {
Network::server_off_content(ui); Network::server_off_content(ui);
} else { } else {
ui.centered_and_justified(|ui| { ui.centered_and_justified(|ui| {
Spinner::new().size(104.0).color(COLOR_YELLOW).ui(ui); Spinner::new().size(104.0).color(Colors::GOLD).ui(ui);
}); });
} }
return; return;
@ -218,51 +209,51 @@ fn draw_peer_stats(ui: &mut egui::Ui, peer: &PeerStats, rounding: [bool; 2]) {
se: if rounding[1] { 8.0 } else { 0.0 }, se: if rounding[1] { 8.0 } else { 0.0 },
}, },
Color32::WHITE, Color32::WHITE,
Stroke { width: 1.0, color: COLOR_GRAY_LIGHT } Stroke { width: 1.0, color: Colors::ITEM_STROKE }
); );
ui.add_space(2.0); ui.add_space(2.0);
ui.horizontal_top(|ui| { ui.horizontal_top(|ui| {
ui.add_space(5.0); ui.add_space(5.0);
ui.heading(RichText::new(PLUGS_CONNECTED) ui.heading(RichText::new(PLUGS_CONNECTED)
.color(Color32::BLACK) .color(Colors::BLACK)
.size(18.0)); .size(18.0));
ui.add_space(3.0); ui.add_space(3.0);
// Draw peer address // Draw peer address
ui.heading(RichText::new(&peer.addr) ui.heading(RichText::new(&peer.addr)
.color(Color32::BLACK) .color(Colors::BLACK)
.size(18.0)); .size(18.0));
}); });
ui.horizontal_top(|ui| { ui.horizontal_top(|ui| {
ui.add_space(6.0); ui.add_space(6.0);
ui.heading(RichText::new(PACKAGE) ui.heading(RichText::new(PACKAGE)
.color(COLOR_DARK) .color(Colors::TITLE)
.size(16.0)); .size(16.0));
ui.add_space(4.0); ui.add_space(4.0);
// Draw peer difficulty and height // Draw peer difficulty and height
ui.heading(RichText::new(peer.total_difficulty.to_string()) ui.heading(RichText::new(peer.total_difficulty.to_string())
.color(COLOR_DARK) .color(Colors::TITLE)
.size(16.0)); .size(16.0));
ui.add_space(2.0); ui.add_space(2.0);
ui.heading(RichText::new(AT).color(COLOR_DARK).size(16.0)); ui.heading(RichText::new(AT).color(Colors::TITLE).size(16.0));
ui.add_space(2.0); ui.add_space(2.0);
ui.heading(RichText::new(peer.height.to_string()) ui.heading(RichText::new(peer.height.to_string())
.color(COLOR_DARK) .color(Colors::TITLE)
.size(16.0)); .size(16.0));
}); });
ui.horizontal_top(|ui| { ui.horizontal_top(|ui| {
ui.add_space(6.0); ui.add_space(6.0);
ui.heading(RichText::new(DEVICES) ui.heading(RichText::new(DEVICES)
.color(COLOR_GRAY) .color(Colors::GRAY)
.size(16.0)); .size(16.0));
ui.add_space(4.0); ui.add_space(4.0);
// Draw peer user-agent // Draw peer user-agent
ui.heading(RichText::new(&peer.user_agent) ui.heading(RichText::new(&peer.user_agent)
.color(COLOR_GRAY) .color(Colors::GRAY)
.size(16.0)); .size(16.0));
}); });
ui.add_space(2.0); ui.add_space(2.0);

View file

@ -15,7 +15,7 @@
use egui::style::Margin; use egui::style::Margin;
use egui_extras::{Size, StripBuilder}; use egui_extras::{Size, StripBuilder};
use crate::gui::colors::{COLOR_DARK, COLOR_YELLOW}; use crate::gui::Colors;
use crate::gui::views::View; use crate::gui::views::View;
pub struct TitlePanelAction<'action> { pub struct TitlePanelAction<'action> {
@ -34,19 +34,17 @@ pub struct TitlePanel {
} }
impl TitlePanel { impl TitlePanel {
const PANEL_SIZE: f32 = 52.0; const PANEL_HEIGHT: f32 = 52.0;
pub fn new(title: &String) -> Self { pub fn new(title: String) -> Self {
Self { title: title.to_uppercase() } Self { title: title.to_uppercase() }
} }
pub fn ui(&self, l: Option<TitlePanelAction>, r: Option<TitlePanelAction>, ui: &mut egui::Ui) { pub fn ui(&self, l: Option<TitlePanelAction>, r: Option<TitlePanelAction>, ui: &mut egui::Ui) {
let Self { title } = self;
egui::TopBottomPanel::top("title_panel") egui::TopBottomPanel::top("title_panel")
.resizable(false) .resizable(false)
.frame(egui::Frame { .frame(egui::Frame {
fill: COLOR_YELLOW, fill: Colors::YELLOW,
inner_margin: Margin::same(0.0), inner_margin: Margin::same(0.0),
outer_margin: Margin::same(0.0), outer_margin: Margin::same(0.0),
stroke: egui::Stroke::NONE, stroke: egui::Stroke::NONE,
@ -54,40 +52,44 @@ impl TitlePanel {
}) })
.show_inside(ui, |ui| { .show_inside(ui, |ui| {
StripBuilder::new(ui) StripBuilder::new(ui)
.size(Size::exact(Self::PANEL_SIZE)) .size(Size::exact(Self::PANEL_HEIGHT))
.vertical(|mut strip| { .vertical(|mut strip| {
strip.strip(|builder| { strip.strip(|builder| {
builder builder
.size(Size::exact(Self::PANEL_SIZE)) .size(Size::exact(Self::PANEL_HEIGHT))
.size(Size::remainder()) .size(Size::remainder())
.size(Size::exact(Self::PANEL_SIZE)) .size(Size::exact(Self::PANEL_HEIGHT))
.horizontal(|mut strip| { .horizontal(|mut strip| {
strip.cell(|ui| { strip.cell(|ui| {
show_action(ui, l.as_ref()); self.draw_action(ui, l);
}); });
strip.cell(|ui| { strip.cell(|ui| {
ui.centered_and_justified(|ui| { self.draw_title(ui);
View::ellipsize_text(ui, title.into(), 20.0, COLOR_DARK);
});
}); });
strip.cell(|ui| { strip.cell(|ui| {
show_action(ui, r.as_ref()); self.draw_action(ui, r);
}); });
}); });
}); });
}); });
}); });
} }
}
fn show_action(ui: &mut egui::Ui, action: Option<&TitlePanelAction>) { fn draw_action(&self, ui: &mut egui::Ui, action: Option<TitlePanelAction>) {
if action.is_some() { if action.is_some() {
let action = action.unwrap(); let action = action.unwrap();
ui.centered_and_justified(|ui| { ui.centered_and_justified(|ui| {
View::title_button(ui, &action.icon, || { View::title_button(ui, &action.icon, || {
(action.on_click)(); (action.on_click)();
});
}); });
}
}
fn draw_title(&self, ui: &mut egui::Ui) {
let Self { title } = self;
ui.centered_and_justified(|ui| {
View::ellipsize_text(ui, title.into(), 20.0, Colors::TITLE);
}); });
} }
} }

View file

@ -12,19 +12,19 @@
// 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::epaint::{Color32, FontId, Rounding, Stroke};
use egui::text::{LayoutJob, TextFormat};
use egui::{Button, PointerState, Response, RichText, Sense, Vec2, Widget}; use egui::{Button, PointerState, Response, RichText, Sense, Vec2, Widget};
use egui::epaint::{Color32, FontId, Rounding, Stroke};
use egui::epaint::text::TextWrapping; use egui::epaint::text::TextWrapping;
use egui::text::{LayoutJob, TextFormat};
use egui_extras::{Size, StripBuilder}; use egui_extras::{Size, StripBuilder};
use crate::gui::colors::{COLOR_DARK, COLOR_GRAY, COLOR_LIGHT, COLOR_GRAY_LIGHT, COLOR_GRAY_DARK, COLOR_YELLOW}; use crate::gui::Colors;
pub struct View; pub struct View;
impl View { impl View {
/// Default stroke around views. /// Default stroke around views.
pub const DEFAULT_STROKE: Stroke = Stroke { width: 1.0, color: Color32::from_gray(190) }; pub const DEFAULT_STROKE: Stroke = Stroke { width: 1.0, color: Colors::STROKE };
/// 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;
@ -56,7 +56,7 @@ impl View {
/// Sub-header with uppercase characters and more lighter color. /// Sub-header with uppercase characters and more lighter color.
pub fn sub_header(ui: &mut egui::Ui, text: String) { pub fn sub_header(ui: &mut egui::Ui, text: String) {
ui.label(RichText::new(text.to_uppercase()).size(16.0).color(COLOR_GRAY_DARK)); ui.label(RichText::new(text.to_uppercase()).size(16.0).color(Colors::SUB_TITLE));
} }
/// Temporary button click optimization for touch screens. /// Temporary button click optimization for touch screens.
@ -77,9 +77,9 @@ impl View {
// Disable stroke around title buttons on hover // Disable stroke around title buttons on hover
ui.style_mut().visuals.widgets.active.bg_stroke = Stroke::NONE; ui.style_mut().visuals.widgets.active.bg_stroke = Stroke::NONE;
let wt = RichText::new(icon.to_string()).size(24.0).color(COLOR_DARK); let wt = RichText::new(icon.to_string()).size(24.0).color(Colors::TITLE);
let br = Button::new(wt) let br = Button::new(wt)
.fill(Color32::TRANSPARENT) .fill(Colors::TRANSPARENT)
.ui(ui).interact(Sense::click_and_drag()); .ui(ui).interact(Sense::click_and_drag());
Self::on_button_click(ui, br, action); Self::on_button_click(ui, br, action);
@ -89,8 +89,8 @@ impl View {
/// Tab button with white background fill color, contains only icon. /// Tab button with white background fill color, contains only icon.
pub fn tab_button(ui: &mut egui::Ui, icon: &str, active: bool, action: impl FnOnce()) { pub fn tab_button(ui: &mut egui::Ui, icon: &str, active: bool, action: impl FnOnce()) {
let text_color = match active { let text_color = match active {
true => { COLOR_GRAY_DARK } true => { Colors::TITLE }
false => { COLOR_DARK } false => { Colors::SUB_TITLE }
}; };
let wt = RichText::new(icon.to_string()).size(24.0).color(text_color); let wt = RichText::new(icon.to_string()).size(24.0).color(text_color);
@ -100,8 +100,8 @@ impl View {
}; };
let color = match active { let color = match active {
true => { COLOR_LIGHT } true => { Colors::FILL }
false => { Color32::WHITE } false => { Colors::WHITE }
}; };
let br = Button::new(wt) let br = Button::new(wt)
.stroke(stroke) .stroke(stroke)
@ -113,7 +113,7 @@ impl View {
/// Draw [`Button`] with specified background fill color. /// Draw [`Button`] with specified background fill color.
pub fn button(ui: &mut egui::Ui, text: String, fill_color: Color32, action: impl FnOnce()) { 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(COLOR_GRAY_DARK); let wt = RichText::new(text.to_uppercase()).size(18.0).color(Colors::BUTTON);
let br = Button::new(wt) let br = Button::new(wt)
.stroke(Self::DEFAULT_STROKE) .stroke(Self::DEFAULT_STROKE)
.fill(fill_color) .fill(fill_color)
@ -139,8 +139,8 @@ impl View {
sw: if r[2] { 8.0 } else { 0.0 }, sw: if r[2] { 8.0 } else { 0.0 },
se: if r[3] { 8.0 } else { 0.0 }, se: if r[3] { 8.0 } else { 0.0 },
}, },
Color32::WHITE, Colors::WHITE,
Stroke { width: 1.0, color: COLOR_GRAY_LIGHT }, Stroke { width: 1.0, color: Colors::ITEM_STROKE },
); );
ui.vertical_centered_justified(|ui| { ui.vertical_centered_justified(|ui| {
@ -150,7 +150,7 @@ impl View {
// Draw box value // Draw box value
let mut job = LayoutJob::single_section(value, TextFormat { let mut job = LayoutJob::single_section(value, TextFormat {
font_id: FontId::proportional(18.0), font_id: FontId::proportional(18.0),
color: Color32::BLACK, color: Colors::BLACK,
.. Default::default() .. Default::default()
}); });
job.wrap = TextWrapping { job.wrap = TextWrapping {
@ -162,7 +162,7 @@ impl View {
ui.label(job); ui.label(job);
// Draw box label // Draw box label
ui.label(RichText::new(label).color(COLOR_GRAY).size(15.0)); ui.label(RichText::new(label).color(Colors::GRAY).size(15.0));
}); });
} }