This commit is contained in:
Andrew Golovashevich 2026-03-10 17:10:14 +03:00
parent 988f009913
commit adcb73594d
11 changed files with 200 additions and 7 deletions

View File

@ -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]

View File

@ -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" }

View File

@ -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;

10
gui/abstract/Cargo.toml Normal file
View 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
View 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
View 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
View 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
View 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
);
}

View 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()
}
}
}

View File

@ -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 {

View File

@ -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();
} }
} }