From b6fe596fa33a283a195f8868f37c97c563c6ce51 Mon Sep 17 00:00:00 2001 From: starlord Date: Fri, 11 Oct 2024 17:05:09 +0300 Subject: [PATCH] layout example --- Cargo.lock | 10 +++ examples/demo/src/main.rs | 2 +- examples/layouts/Cargo.toml | 12 +++ examples/layouts/README.md | 7 ++ examples/layouts/src/main.rs | 154 +++++++++++++++++++++++++++++++++++ src/graph_view.rs | 13 +++ src/helpers.rs | 10 +-- 7 files changed, 202 insertions(+), 6 deletions(-) create mode 100644 examples/layouts/Cargo.toml create mode 100644 examples/layouts/README.md create mode 100644 examples/layouts/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 34953e4..b124ecd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3348,6 +3348,16 @@ dependencies = [ "petgraph", ] +[[package]] +name = "layouts" +version = "0.1.0" +dependencies = [ + "eframe", + "egui 0.29.0", + "egui_graphs 0.22.0", + "petgraph", +] + [[package]] name = "lazy_static" version = "1.5.0" diff --git a/examples/demo/src/main.rs b/examples/demo/src/main.rs index 6b117cf..49dc394 100644 --- a/examples/demo/src/main.rs +++ b/examples/demo/src/main.rs @@ -9,7 +9,7 @@ use egui_graphs::{random_graph, DefaultGraphView, Edge, Graph, Node}; use fdg::fruchterman_reingold::{FruchtermanReingold, FruchtermanReingoldConfiguration}; use fdg::nalgebra::{Const, OPoint}; use fdg::{Force, ForceGraph}; -use petgraph::stable_graph::{DefaultIx, EdgeIndex, NodeIndex, StableGraph}; +use petgraph::stable_graph::{DefaultIx, EdgeIndex, NodeIndex}; use petgraph::Directed; use rand::Rng; diff --git a/examples/layouts/Cargo.toml b/examples/layouts/Cargo.toml new file mode 100644 index 0000000..ffa91b3 --- /dev/null +++ b/examples/layouts/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "layouts" +version = "0.1.0" +authors = ["Dmitrii Samsonov "] +license = "MIT" +edition = "2021" + +[dependencies] +egui_graphs = { path = "../../" } +egui = "0.29" +eframe = "0.29" +petgraph = "0.6" diff --git a/examples/layouts/README.md b/examples/layouts/README.md new file mode 100644 index 0000000..17210be --- /dev/null +++ b/examples/layouts/README.md @@ -0,0 +1,7 @@ +# Layouts +Example of usage of different lyouts implemented by `egui_graphs`. + +## run +```bash +cargo run --release -p layouts +``` \ No newline at end of file diff --git a/examples/layouts/src/main.rs b/examples/layouts/src/main.rs new file mode 100644 index 0000000..e1fb859 --- /dev/null +++ b/examples/layouts/src/main.rs @@ -0,0 +1,154 @@ +use eframe::{run_native, App, CreationContext, NativeOptions}; +use egui::Context; +use egui_graphs::{ + random_graph, DefaultEdgeShape, DefaultNodeShape, Graph, GraphView, LayoutHierarchical, + LayoutRandom, LayoutStateHierarchical, LayoutStateRandom, +}; +use petgraph::{stable_graph::DefaultIx, Directed}; + +#[derive(Clone, PartialEq)] +enum Layout { + Hierarchical, + Random, +} + +#[derive(Clone)] +struct Settings { + layout: Layout, + num_nodes: usize, + num_edges: usize, +} +pub struct LayoutsApp { + settings: Settings, + g: Graph, +} + +impl LayoutsApp { + fn new(_: &CreationContext<'_>) -> Self { + let settings = Settings { + layout: Layout::Hierarchical, + num_nodes: 25, + num_edges: 25, + }; + Self { + settings: settings.clone(), + g: random_graph(settings.num_nodes, settings.num_edges), + } + } + + fn clear_cache(&mut self, ui: &mut egui::Ui) { + match self.settings.layout { + Layout::Hierarchical => { + GraphView::< + (), + (), + Directed, + DefaultIx, + DefaultNodeShape, + DefaultEdgeShape, + LayoutStateHierarchical, + LayoutHierarchical, + >::clear_cache(ui); + } + Layout::Random => { + GraphView::< + (), + (), + Directed, + DefaultIx, + DefaultNodeShape, + DefaultEdgeShape, + LayoutStateRandom, + LayoutRandom, + >::clear_cache(ui); + } + }; + } +} + +impl App for LayoutsApp { + fn update(&mut self, ctx: &Context, _: &mut eframe::Frame) { + egui::SidePanel::right("right_panel") + .min_width(250.) + .show(ctx, |ui| { + ui.vertical(|ui| { + ui.horizontal(|ui| { + ui.label("Layout"); + if ui + .radio_value( + &mut self.settings.layout, + Layout::Hierarchical, + "Hierarchical", + ) + .changed() + { + self.clear_cache(ui); + }; + if ui + .radio_value(&mut self.settings.layout, Layout::Random, "Random") + .changed() + { + self.clear_cache(ui); + }; + }); + ui.horizontal(|ui| { + ui.label("Number of nodes"); + if ui + .add(egui::Slider::new(&mut self.settings.num_nodes, 1..=100)) + .changed() + { + self.clear_cache(ui); + self.g = random_graph(self.settings.num_nodes, self.settings.num_edges); + }; + }); + ui.horizontal(|ui| { + ui.label("Number of edges"); + if ui + .add(egui::Slider::new(&mut self.settings.num_edges, 1..=100)) + .changed() + { + self.clear_cache(ui); + self.g = random_graph(self.settings.num_nodes, self.settings.num_edges); + }; + }); + }); + }); + egui::CentralPanel::default().show(ctx, |ui| { + match self.settings.layout { + Layout::Hierarchical => { + ui.add(&mut GraphView::< + _, + _, + _, + _, + _, + _, + LayoutStateHierarchical, + LayoutHierarchical, + >::new(&mut self.g)); + } + Layout::Random => { + ui.add(&mut GraphView::< + _, + _, + _, + _, + _, + _, + LayoutStateRandom, + LayoutRandom, + >::new(&mut self.g)); + } + }; + }); + } +} + +fn main() { + run_native( + "egui_graphs_layouts_demo", + NativeOptions::default(), + Box::new(|cc| Ok(Box::new(LayoutsApp::new(cc)))), + ) + .unwrap(); +} diff --git a/src/graph_view.rs b/src/graph_view.rs index c69aa3e..6067d30 100644 --- a/src/graph_view.rs +++ b/src/graph_view.rs @@ -174,11 +174,24 @@ where self } + /// Clears cached values of layout and metadata. + pub fn clear_cache(ui: &mut Ui) { + GraphView::::reset_metadata(ui); + GraphView::::reset_layout(ui); + } + /// Resets navigation metadata pub fn reset_metadata(ui: &mut Ui) { Metadata::default().save(ui); } + /// Resets layout state + pub fn reset_layout(ui: &mut Ui) { + ui.data_mut(|data| { + data.insert_persisted(Id::new(KEY_LAYOUT), S::default()); + }); + } + #[cfg(feature = "events")] /// Allows to supply channel where events happening in the graph will be reported. pub fn with_events(mut self, events_publisher: &'a Sender) -> Self { diff --git a/src/helpers.rs b/src/helpers.rs index 3472f78..aefb5b9 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -251,17 +251,17 @@ pub fn node_size Graph { +pub fn random_graph(num_nodes: usize, num_edges: usize) -> Graph { let mut rng = rand::thread_rng(); let mut graph = StableGraph::new(); - for _ in 0..node_count { + for _ in 0..num_nodes { graph.add_node(()); } - for _ in 0..edge_count { - let source = rng.gen_range(0..node_count); - let target = rng.gen_range(0..node_count); + for _ in 0..num_edges { + let source = rng.gen_range(0..num_nodes); + let target = rng.gen_range(0..num_nodes); graph.add_edge(NodeIndex::new(source), NodeIndex::new(target), ()); }