Gui stub
This commit is contained in:
parent
988f009913
commit
adcb73594d
@ -4,7 +4,9 @@ members = [
|
|||||||
"app",
|
"app",
|
||||||
"network/icmp",
|
"network/icmp",
|
||||||
"network/abstract",
|
"network/abstract",
|
||||||
"network/windows"
|
"network/windows",
|
||||||
|
"gui/abstract",
|
||||||
|
"gui/egui"
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.lints]
|
[workspace.lints]
|
||||||
|
|||||||
@ -7,9 +7,8 @@ edition = "2024"
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
eframe = { version = "0.33.3", default-features = false, features = ["default_fonts", "glow"] }
|
|
||||||
egui_extras = { version = "0.33.3" }
|
|
||||||
bgtu-networks-2-network-abstract = { path = "../network/abstract" }
|
bgtu-networks-2-network-abstract = { path = "../network/abstract" }
|
||||||
|
bgtu-networks-2-gui-abstract = { path = "../gui/abstract" }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
bgtu-networks-2-network-windows = { path = "../network/windows" }
|
bgtu-networks-2-network-windows = { path = "../network/windows" }
|
||||||
@ -1,5 +1,6 @@
|
|||||||
use bgtu_networks_2_network_abstract::{Address, NetworkContext, NetworkScope, ServersContext};
|
use bgtu_networks_2_network_abstract::{Address, NetworkContext, NetworkScope, ServersContext};
|
||||||
use bgtu_networks_2_network_windows::winsocks_scope_2_2;
|
use bgtu_networks_2_network_windows::winsocks_scope_2_2;
|
||||||
|
use bgtu_networks_2_gui_abstract::ServersStorage;
|
||||||
|
|
||||||
// mod data;
|
// mod data;
|
||||||
|
|
||||||
@ -43,4 +44,4 @@ impl<A: Address> ServersContext<A> for Servers2NetworkCtxTestImpl<A> {
|
|||||||
println!("{} err", addr.to_string())
|
println!("{} err", addr.to_string())
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
10
gui/abstract/Cargo.toml
Normal file
10
gui/abstract/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "bgtu-networks-2-gui-abstract"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bgtu-networks-2-network-abstract = { path = "../../network/abstract" }
|
||||||
11
gui/abstract/src/lib.rs
Normal file
11
gui/abstract/src/lib.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use bgtu_networks_2_network_abstract::Address;
|
||||||
|
|
||||||
|
pub trait ServersStorage {
|
||||||
|
type A: Address;
|
||||||
|
|
||||||
|
fn add_server(&mut self, addr: Self::A, memo: String);
|
||||||
|
fn remove_server(&mut self, addr: &Self::A);
|
||||||
|
|
||||||
|
// type TimeIterator: Iterator<Item = Option<u128>>;
|
||||||
|
fn iter_servers(&self) -> impl Iterator<Item = (&Self::A, &str, impl Iterator<Item = Option<u128>>)>;
|
||||||
|
}
|
||||||
13
gui/egui/Cargo.toml
Normal file
13
gui/egui/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "bgtu-networks-2-gui-egui"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
eframe = { version = "0.33.3", default-features = false, features = ["default_fonts", "glow"] }
|
||||||
|
egui_extras = { version = "0.33.3" }
|
||||||
|
bgtu-networks-2-gui-abstract = { path = "../abstract" }
|
||||||
|
bgtu-networks-2-network-abstract = { path = "../../network/abstract" }
|
||||||
104
gui/egui/src/lib.rs
Normal file
104
gui/egui/src/lib.rs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
use bgtu_networks_2_network_abstract::Address;
|
||||||
|
mod plot;
|
||||||
|
mod subwindows;
|
||||||
|
|
||||||
|
use crate::plot::draw_plot;
|
||||||
|
use bgtu_networks_2_gui_abstract::ServersStorage;
|
||||||
|
use eframe::egui::Context;
|
||||||
|
use eframe::{App, Frame, egui};
|
||||||
|
use egui_extras::{Column, TableBuilder};
|
||||||
|
|
||||||
|
pub fn run_eframe_gui<Ctx: ServersStorage>(ctx: &mut Ctx) -> eframe::Result {
|
||||||
|
let options = eframe::NativeOptions {
|
||||||
|
viewport: egui::ViewportBuilder::default().with_inner_size([640.0, 400.0]),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
eframe::run_native(
|
||||||
|
"ICMP status monitor",
|
||||||
|
options,
|
||||||
|
Box::new(|_cc| {
|
||||||
|
Ok(Box::new(EguiApp {
|
||||||
|
ctx,
|
||||||
|
modal_windows: ModalWindows::Root,
|
||||||
|
}))
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
enum ModalWindows {
|
||||||
|
Root,
|
||||||
|
Add,
|
||||||
|
Edit,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EguiApp<'a, Ctx> {
|
||||||
|
ctx: &'a mut Ctx,
|
||||||
|
modal_windows: ModalWindows,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Ctx: ServersStorage> App for EguiApp<'_, Ctx> {
|
||||||
|
fn update(&mut self, ctx: &Context, frame: &mut Frame) {
|
||||||
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
ui.add_enabled_ui(self.modal_windows == ModalWindows::Root, |ui| {
|
||||||
|
if ui.button("Add server").clicked() {
|
||||||
|
self.modal_windows = ModalWindows::Add
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
TableBuilder::new(ui)
|
||||||
|
.striped(true) // Alternating row colors
|
||||||
|
.resizable(true)
|
||||||
|
.vscroll(true)
|
||||||
|
.columns(Column::remainder(), 3)
|
||||||
|
.header(20.0, |mut r| {
|
||||||
|
r.col(|ui| {
|
||||||
|
ui.label("Address");
|
||||||
|
});
|
||||||
|
r.col(|ui| {
|
||||||
|
ui.label("Memo");
|
||||||
|
});
|
||||||
|
r.col(|ui| {
|
||||||
|
ui.label("Graph");
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.body(|mut t| {
|
||||||
|
for (addr, memo, pings) in self.ctx.iter_servers() {
|
||||||
|
t.row(20.0, |mut r| {
|
||||||
|
r.col(|ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.add_enabled_ui(
|
||||||
|
self.modal_windows == ModalWindows::Root,
|
||||||
|
|ui| {
|
||||||
|
if ui.button("-").clicked() {
|
||||||
|
self.modal_windows = ModalWindows::Add
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ui.label(addr.to_string());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
r.col(|ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.add(egui::Label::new(memo).wrap());
|
||||||
|
ui.add_enabled_ui(
|
||||||
|
self.modal_windows == ModalWindows::Root,
|
||||||
|
|ui| {
|
||||||
|
if ui.button("-").clicked() {
|
||||||
|
self.modal_windows = ModalWindows::Add
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
r.col(|ui| {
|
||||||
|
draw_plot(ui, pings);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
14
gui/egui/src/plot.rs
Normal file
14
gui/egui/src/plot.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use eframe::egui::{Color32, Rect, StrokeKind, Ui};
|
||||||
|
use eframe::epaint::{Pos2, Stroke};
|
||||||
|
|
||||||
|
pub(crate) fn draw_plot(ui: &mut Ui, time: impl Iterator<Item = Option<u128>>) {
|
||||||
|
let rect = ui.available_size();
|
||||||
|
let canvas = ui.painter();
|
||||||
|
canvas.rect(
|
||||||
|
Rect::from_min_size(Pos2::new(0.0, 0.0), rect),
|
||||||
|
0,
|
||||||
|
Color32::from_rgb(255, 255, 255),
|
||||||
|
Stroke::new(1.0, Color32::from_rgb(127, 127, 127)),
|
||||||
|
StrokeKind::Inside
|
||||||
|
);
|
||||||
|
}
|
||||||
39
gui/egui/src/subwindows.rs
Normal file
39
gui/egui/src/subwindows.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use eframe::egui;
|
||||||
|
use eframe::egui::{Frame, Ui, ViewportBuilder};
|
||||||
|
|
||||||
|
pub fn subwindow(
|
||||||
|
ui: &mut Ui,
|
||||||
|
id: &str,
|
||||||
|
title: &str,
|
||||||
|
extra_settings: impl FnOnce(ViewportBuilder) -> ViewportBuilder,
|
||||||
|
mut content: impl FnMut(&mut Ui),
|
||||||
|
) -> Response {
|
||||||
|
let id = egui::ViewportId::from_hash_of(id);
|
||||||
|
let vb = extra_settings(ViewportBuilder::default().with_title(title));
|
||||||
|
|
||||||
|
let closed = ui.ctx().show_viewport_immediate(id, vb, |ui, _| {
|
||||||
|
egui::CentralPanel::default()
|
||||||
|
.frame(Frame::default().inner_margin(0.0))
|
||||||
|
.show(ui, |ui| content(ui));
|
||||||
|
|
||||||
|
return ui.input(|i| i.viewport().close_requested());
|
||||||
|
});
|
||||||
|
|
||||||
|
return Response { closed };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Response {
|
||||||
|
closed: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Response {
|
||||||
|
pub fn close_requested(&self) -> bool {
|
||||||
|
return self.closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_close(&self, cb: impl FnOnce()) {
|
||||||
|
if self.closed {
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
pub trait Address: Sized + Clone {
|
pub trait Address: Sized + Clone {
|
||||||
fn parse(raw: &str) -> Result<Self, String>;
|
fn parse(raw: &str) -> Result<Self, String>;
|
||||||
fn to_string(self) -> String;
|
fn to_string(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait NetworkContext {
|
pub trait NetworkContext {
|
||||||
|
|||||||
@ -45,7 +45,7 @@ impl Address for WindowsAddressAny {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string(self) -> String {
|
fn to_string(&self) -> String {
|
||||||
let mut buffer = [0u16; 1024];
|
let mut buffer = [0u16; 1024];
|
||||||
let mut buf_size = buffer.len() as u32;
|
let mut buf_size = buffer.len() as u32;
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -123,7 +123,7 @@ impl Address for WindowsAddressKnown {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string(self) -> String {
|
fn to_string(&self) -> String {
|
||||||
return self.any.to_string();
|
return self.any.to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user