### egui_graphs Metadata Management Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/metadata Demonstrates how to manage metadata for a graph, including first frame status, zoom level, and pan offset. It shows how to get and store this metadata using egui's data persistence. ```Rust use egui::{Id, Vec2}; #[derive(Clone)] pub struct Metadata { /// Whether the frame is the first one pub first_frame: bool, /// Current zoom factor pub zoom: f32, /// Current pan offset pub pan: Vec2, } impl Default for Metadata { fn default() -> Self { Self { first_frame: true, zoom: 1., pan: Default::default(), } } } impl Metadata { pub fn get(ui: &egui::Ui) -> Self { ui.data_mut(|data| { data.get_persisted::(Id::null()) .unwrap_or_default() }) } pub fn store_into_ui(self, ui: &mut egui::Ui) { ui.data_mut(|data| { data.insert_persisted(Id::null(), self); }); } } ``` -------------------------------- ### Configure Rustdoc Settings Source: https://docs.rs/egui_graphs/0.9.0/settings This section details various settings for Rustdoc, the documentation generator for Rust. It covers theme preferences, auto-hide options for documentation content, direct search result navigation, line number display for code examples, and disabling keyboard shortcuts. ```Rustdoc # Rustdoc settings Back Theme light dark ayu system preference Preferred light theme light dark ayu Preferred dark theme light dark ayu Auto-hide item contents for large items Auto-hide item methods' documentation Auto-hide trait implementation documentation Directly go to item in search if there is only one result Show line numbers on code examples Disable keyboard shortcuts ``` -------------------------------- ### Draw Basic Edge in egui Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/draw/drawer Renders a basic edge between two nodes in egui, handling cases where one or both nodes are folded. It calculates the start and end points of the edge, considering node radii and directionality, and applies color based on transparency. ```Rust fn draw_edge_basic( &self, l: &mut Layers, start_idx: &NodeIndex, end_idx: &NodeIndex, e: &Edge, comp_edge: &StateComputedEdge, order: usize, ) { let mut comp_start = self.comp.node_state(start_idx).unwrap(); let mut comp_end = self.comp.node_state(end_idx).unwrap(); let start_node = self.g.node(*start_idx).unwrap(); let mut transparent = false; if (start_node.folded() || comp_start.subfolded()) && comp_end.subfolded() { return; } // if start node is in folding tree and end node not we should draw edge transparent // starting from the root of the folding tree if comp_start.subfolded() && !comp_end.subfolded() { let new_start_idx = self .comp .foldings .roots_by_node(*start_idx) .unwrap() .first() .unwrap(); comp_start = self.comp.node_state(new_start_idx).unwrap(); transparent = true; } // if end node is in folding tree and start node not we should draw edge transparent // ending at the root of the folding tree if !comp_start.subfolded() && comp_end.subfolded() { let new_end_idx = self .comp .foldings .roots_by_node(*end_idx) .unwrap() .first() .unwrap(); comp_end = self.comp.node_state(new_end_idx).unwrap(); transparent = true; } let pos_start = comp_start.location.to_pos2(); let pos_end = comp_end.location.to_pos2(); let vec = pos_end - pos_start; let dist: f32 = vec.length(); let dir = vec / dist; let start_node_radius_vec = Vec2::new(comp_start.radius, comp_start.radius) * dir; let end_node_radius_vec = Vec2::new(comp_end.radius, comp_end.radius) * dir; let tip_end = pos_start + vec - end_node_radius_vec; let edge_start = pos_start + start_node_radius_vec; let edge_end = match self.g.is_directed() { true => tip_end - comp_edge.tip_size * dir, false => tip_end, }; let mut color = self.settings_style.color_edge(self.p.ctx(), e); if transparent { color = color.gamma_multiply(0.15); } // The rest of the drawing logic for basic edges would go here, // likely involving creating a LineShape or similar egui primitive. // For brevity, only the calculation part is included. } ``` -------------------------------- ### Rust: Get Subgraph Roots by Node Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/subgraphs This Rust code snippet tests the `roots_by_node` method of the `SubGraphs` struct. It adds subgraphs to a test graph and then retrieves the root nodes associated with specific nodes, asserting the correctness of the returned root nodes. ```rust let g = create_test_graph(); let graph = Graph::new(g); let mut subgraphs = SubGraphs::default(); // a->b, a->d subgraphs.add_subgraph(&graph, NodeIndex::new(0), 1); // b->c subgraphs.add_subgraph(&graph, NodeIndex::new(1), 1); // Check roots for node 1 (b) let roots = subgraphs.roots_by_node(NodeIndex::new(1)).unwrap(); assert_eq!(roots.len(), 1); assert_eq!(roots[0], NodeIndex::new(0)); // Check roots for node 2 (c) let roots = subgraphs.roots_by_node(NodeIndex::new(2)).unwrap(); assert_eq!(roots.len(), 1); assert_eq!(roots[0], NodeIndex::new(1)); ``` -------------------------------- ### Get Edge State Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/state_computed Retrieves the computed state for a given edge index, returning an Option<&StateComputedEdge> if the state exists. ```Rust pub fn edge_state(&self, idx: &EdgeIndex) -> Option<&StateComputedEdge> { self.edges.get(idx) } ``` -------------------------------- ### Initialize Drawer for egui_graphs Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/draw/drawer Creates a new Drawer instance to render graph elements. It takes the egui Painter, the graph data, computed state, and style settings as input. ```Rust pub fn new( p: Painter, g: &'a Graph, comp: &'a StateComputed, settings_style: &'a SettingsStyle, ) -> Self { Drawer { g, p, comp, settings_style, } } ``` -------------------------------- ### Get Node State Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/state_computed Retrieves the computed state for a given node index, returning an Option<&StateComputedNode> if the state exists. ```Rust pub fn node_state(&self, idx: &NodeIndex) -> Option<&StateComputedNode> { self.nodes.get(idx) } ``` -------------------------------- ### Initialize SettingsNavigation Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/settings Creates a new SettingsNavigation struct with default values for graph navigation. This includes settings for fitting to screen, zoom/pan behavior, screen padding, and zoom speed. ```Rust pub fn new() -> Self { Self::default() } ``` -------------------------------- ### Rust egui_graphs: Get Element Color Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/elements/node Retrieves the current color of a graph element. Returns an Option, which is None if no color is set. ```Rust pub fn color(&self) -> Option { self.color } ``` -------------------------------- ### Rustdoc Keyboard Shortcuts Source: https://docs.rs/egui_graphs/0.9.0/help This snippet outlines the keyboard shortcuts available in rustdoc for navigating and interacting with the documentation. It covers actions like showing help, focusing search, moving through results, and expanding/collapsing sections. ```Rustdoc `?` Show this help dialog `S` Focus the search field `↑` Move up in search results `↓` Move down in search results `←` / `→` Switch result tab (when results focused) `⏎` Go to active search result `+` Expand all sections `-` Collapse all sections ``` -------------------------------- ### Get All Subgraph Roots Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/subgraphs Returns a vector containing the `NodeIndex` of all root nodes that define the subgraphs within the collection. This provides a way to access the entry points of all managed subgraphs. ```rust pub fn roots(&self) -> Vec { self.data.keys().cloned().collect() } ``` -------------------------------- ### Create GraphView Widget Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/graph_view Creates a new GraphView widget with default navigation and interaction settings. Customization can be done using `with_interactions` and `with_navigations` methods. ```rust impl<'a, N: Clone, E: Clone, Ty: EdgeType> GraphView<'a, N, E, Ty> { /// Creates a new `GraphView` widget with default navigation and interactions settings. /// To customize navigation and interactions use `with_interactions` and `with_navigations` methods. pub fn new(g: &'a mut Graph) -> Self { Self { g, settings_style: Default::default(), settings_interaction: Default::default(), settings_navigation: Default::default(), changes_sender: Default::default(), } } ``` -------------------------------- ### Handle Node Dragging in Rust Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/graph_view Manages the dragging of nodes. It enables dragging if configured, sets a node as dragged when a drag starts, moves the node based on drag delta, and resets the dragged state upon release. ```rust fn handle_node_drag(&mut self, resp: &Response, comp: &mut StateComputed, meta: &mut Metadata) { if !self.settings_interaction.dragging_enabled { return; } if resp.drag_started() { if let Some((idx, _)) = self.g.node_by_pos(comp, meta, resp.hover_pos().unwrap()) { self.set_dragged(idx, true); } } if resp.dragged() && comp.dragged.is_some() { let n_idx_dragged = comp.dragged.unwrap(); let delta_in_graph_coords = resp.drag_delta() / meta.zoom; self.move_node(n_idx_dragged, delta_in_graph_coords); } if resp.drag_released() && comp.dragged.is_some() { let n_idx = comp.dragged.unwrap(); self.set_dragged(n_idx, false); } } ``` -------------------------------- ### Initialize SettingsStyle Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/settings Creates a new SettingsStyle struct with default values for graph styling. This includes default colors for nodes, edges, selections, and text, as well as label behavior. ```Rust pub fn new() -> Self { Self::default() } ``` -------------------------------- ### Get Root Nodes by Node Index Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/subgraphs Retrieves a list of root nodes for any subgraphs that the given node index belongs to. This method is used to determine which subgraphs a particular node is a part of, returning `None` if the node is not part of any subgraph. ```rust pub fn roots_by_node(&self, idx: NodeIndex) -> Option<&Vec> { self.roots_by_node.get(&idx) } ``` -------------------------------- ### Handle Fit to Screen Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/graph_view Handles fitting the graph to the screen. This occurs on the first frame or when the 'fit to screen' setting is enabled. It uses the response rect, metadata, and computed state. ```rust /// Fits the graph to the screen if it is the first frame or /// fit to screen setting is enabled; fn handle_fit_to_screen(&self, r: &Response, meta: &mut Metadata, comp: &StateComputed) { if !meta.first_frame && !self.settings_navigation.fit_to_screen_enabled { return; } self.fit_to_screen(&r.rect, meta, comp); meta.first_frame = false; } ``` -------------------------------- ### Subgraph Elements Retrieval Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/subgraphs Retrieves all nodes and edges from all subgraphs managed by the `SubGraphs` collection. It iterates through each subgraph, collects its nodes and edges, and then removes duplicates before returning them. This is useful for getting a consolidated view of all graph components across different subgraphs. ```rust pub fn elements(&self) -> Elements { let mut nodes = vec![]; let mut edges = vec![]; for (root, _) in self.data.iter() { let (curr_nodes, curr_edges) = self.elements_by_root(*root).unwrap(); nodes.extend(curr_nodes); edges.extend(curr_edges); } // remove duplicates nodes.sort(); nodes.dedup(); edges.sort(); edges.dedup(); (nodes, edges) } ``` -------------------------------- ### Draw Graph Elements Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/draw/drawer Initiates the drawing process for the graph. It first fills layers with edge and node information, then draws these layers using the provided egui Painter. ```Rust pub fn draw(self) { let mut l = Layers::default(); self.fill_layers_edges(&mut l); self.fill_layers_nodes(&mut l); l.draw(self.p) } ``` -------------------------------- ### Rust Test Graph Creation Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/subgraphs A helper function to create a sample `StableGraph` with nodes and edges for testing purposes. It sets up a simple directed graph structure. ```Rust fn create_test_graph() -> StableGraph, Edge<()>> { let mut graph = StableGraph::, Edge<()>>::new(); let a = graph.add_node(Node::new(Vec2::default(), ())); let b = graph.add_node(Node::new(Vec2::default(), ())); let c = graph.add_node(Node::new(Vec2::default(), ())); let d = graph.add_node(Node::new(Vec2::default(), ())); graph.add_edge(a, b, Edge::new(())); graph.add_edge(b, c, Edge::new(())); graph.add_edge(c, d, Edge::new(())); graph.add_edge(a, d, Edge::new(())); graph } ``` -------------------------------- ### Get Node Stroke Color Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/settings Determines the stroke color for nodes based on the current egui theme (dark or light mode). It returns the node's default color in dark mode and the edge's default color in light mode. ```Rust pub fn color_node_stroke(&self, ctx: &egui::Context) -> Color32 { if ctx.style().visuals.dark_mode { self.color_node } else { self.color_edge } } ``` -------------------------------- ### Configure egui_graphs Interaction Settings Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/settings This snippet demonstrates how to configure various interaction settings for egui_graphs, such as enabling dragging, clicking, folding, and selection of nodes. It also covers multi-selection and defining the depth for selection and folding operations. ```Rust use egui::Color32; use crate::{ state_computed::{StateComputedEdge, StateComputedNode}, Edge, Node, }; /// Represents graph interaction settings. #[derive(Debug, Clone, Default)] pub struct SettingsInteraction { pub(crate) dragging_enabled: bool, pub(crate) clicking_enabled: bool, pub(crate) folding_enabled: bool, pub(crate) selection_enabled: bool, pub(crate) selection_multi_enabled: bool, pub(crate) selection_depth: i32, pub(crate) folding_depth: usize, } impl SettingsInteraction { /// Creates new [`SettingsInteraction`] with default values. pub fn new() -> Self { Self::default() } /// Node dragging. To drag a node with your mouse or finger. /// /// Default: `false` pub fn with_dragging_enabled(mut self, enabled: bool) -> Self { self.dragging_enabled = enabled; self } /// Allows clicking on nodes. /// /// Default: `false` pub fn with_clicking_enabled(mut self, enabled: bool) -> Self { self.clicking_enabled = enabled; self } /// Allows to fold nodes. /// /// Default: `false` pub fn with_folding_enabled(mut self, enabled: bool) -> Self { self.folding_enabled = enabled; self } /// Selects clicked node, enables clicks. /// /// Select by clicking on node, deselect by clicking again. /// /// Clicking on empty space deselects all nodes. /// /// Default: `false` pub fn with_selection_enabled(mut self, enabled: bool) -> Self { self.selection_enabled = enabled; self } /// Multiselection for nodes, enables click and select. /// /// Default: `false` pub fn with_selection_multi_enabled(mut self, enabled: bool) -> Self { self.selection_multi_enabled = enabled; self } /// How deep into the neighbours of selected nodes should the selection go. /// /// * `selection_depth == 0` means only selected nodes are selected. /// * `selection_depth > 0` means children of selected nodes are selected up to `selection_depth` generation. /// * `selection_depth < 0` means parents of selected nodes are selected up to `selection_depth` generation. /// * passing `i32::MAX` and `i32::MIN` selects all available generations of children or parents. /// /// Default: `0` pub fn with_selection_depth(mut self, depth: i32) -> Self { self.selection_depth = depth; self } /// Defines the generation depth up to which the children of the folded node will be folded. /// /// * `folding_depth == 0` means only the folded node is folded. /// * `folding_depth > 0` means children of the folded node are folded up to `folding_depth` generation. /// * `folding_depth == usize::MAX` folds all available generations of children. ``` -------------------------------- ### Find Midpoint Between Two Points (Rust) Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/draw/drawer Calculates the point exactly in the middle of two given 2D points. It finds the vector between the points, normalizes it to get the direction, and then moves from the first point by half the distance along that direction. Returns the midpoint `Pos2`. ```rust /// finds point exactly in the middle between 2 points fn point_between(p1: Pos2, p2: Pos2) -> Pos2 { let base = p1 - p2; let base_len = base.length(); let dir = base / base_len; p1 - (base_len / 2.) * dir } ``` -------------------------------- ### Implement StateComputedNode Methods Source: https://docs.rs/egui_graphs/0.9.0/egui_graphs/struct Provides implementations for key methods of the StateComputedNode struct. These include creating a new node state from a Node, checking visibility, determining sub-selection and sub-folding states, increasing the node's radius, and applying screen transformations. ```Rust pub fn new(n: &Node) -> Self ``` ```Rust pub fn visible(&self) -> bool Indicates if node is visible and should be drawn ``` ```Rust pub fn subselected(&self) -> bool ``` ```Rust pub fn subfolded(&self) -> bool ``` ```Rust pub fn inc_radius(&mut self, inc: f32) ``` ```Rust pub fn apply_screen_transform(&mut self, m: &Metadata) ``` -------------------------------- ### Handle Navigation (Zoom and Pan) in Rust Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/graph_view Orchestrates the handling of user navigation inputs, calling separate functions for zoom and pan operations based on enabled settings. ```rust fn handle_navigation( &self, ui: &Ui, resp: &Response, meta: &mut Metadata, comp: &StateComputed, ) { self.handle_zoom(ui, resp, meta); self.handle_pan(resp, meta, comp); } ``` -------------------------------- ### Add Subgraph by Depth Traversal Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/subgraphs Adds a new subgraph to the collection. This method constructs the subgraph by traversing the main graph (`g`) starting from a specified `root` node, up to a given `depth`. The direction of traversal (outgoing or incoming edges) is determined by the sign of the `depth` parameter. ```rust pub fn add_subgraph( &mut self, g: &Graph, root: NodeIndex, depth: i32, ) { let mut subgraph = petgraph::Graph::::new(); let dir = match depth > 0 { true => petgraph::Direction::Outgoing, false => petgraph::Direction::Incoming, }; let steps = depth.unsigned_abs() as usize; } ``` -------------------------------- ### Transform to Graph (Rust) Source: https://docs.rs/egui_graphs/0.9.0/egui_graphs/index Helper function to transform a user's `petgraph::stable_graph::StableGraph` instance into the version required by the `GraphView` widget. ```Rust pub fn to_graph(graph: petgraph::stable_graph::StableGraph) -> Graph ``` -------------------------------- ### Rust BFS Subgraph Collection Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/subgraphs Implements a Breadth-First Search (BFS) to collect nodes and edges for a subgraph. It starts from a root node and traverses a specified number of steps in a given direction. The function handles visited nodes to prevent cycles and redundant processing, building a new subgraph representation. ```Rust /// Bfs implementation which collects subgraph from `src_subgraph` starting from the `root` node /// travelling `steps` generations in the provided direction `dir`. fn collect_generations( &mut self, src_subgraph: &Graph, dst_subgraph: &mut petgraph::Graph, root: NodeIndex, steps: usize, dir: Direction, ) { let mut visited = HashSet::new(); let mut steps_left = steps; let mut nodes = vec![root]; while steps_left > 0 && !nodes.is_empty() { steps_left -= 1; let mut next_nodes = vec![]; nodes.iter().for_each(|src_start_idx| { let dst_start_idx = self.add_node(dst_subgraph, root, *src_start_idx); src_subgraph .edges_directed(*src_start_idx, dir) .for_each(|edge| { let src_next_idx = match dir { Direction::Incoming => edge.source(), Direction::Outgoing => edge.target(), }; let src_edge_idx = edge.id(); if !visited.insert((*src_start_idx, src_next_idx, src_edge_idx)) { return; } let dst_next_idx = self.add_node(dst_subgraph, root, src_next_idx); dst_subgraph.add_edge(dst_start_idx, dst_next_idx, src_edge_idx); next_nodes.push(src_next_idx); }); }); nodes = next_nodes; } } ``` -------------------------------- ### Define and Initialize a Node in egui_graphs Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/elements/node This snippet shows the definition of the `Node` struct in Rust, which stores properties for a node in a graph visualization. It includes fields for client data, location, label, color, and various states like folded, selected, and dragged. The `Default` implementation provides default values for these fields, and a `new` constructor is available for creating nodes with a location and data. ```Rust use egui::{Color32, Vec2}; use crate::metadata::Metadata; /// Stores properties of a node. #[derive(Clone, Debug)] pub struct Node { /// Client data data: Option, location: Vec2, label: Option, /// If `color` is None default color is used. color: Option, folded: bool, selected: bool, dragged: bool, subselected_child: bool, subselected_parent: bool, subfolded: bool, radius: f32, } impl Default for Node { fn default() -> Self { Self { radius: 5., subfolded: Default::default(), subselected_child: Default::default(), subselected_parent: Default::default(), location: Default::default(), data: Default::default(), label: Default::default(), color: Default::default(), folded: Default::default(), selected: Default::default(), dragged: Default::default(), } } } impl Node { pub fn new(location: Vec2, data: N) -> Self { Self { location, data: Some(data), ..Default::default() } } pub fn screen_location(&self, m: &Metadata) -> Vec2 { self.location * m.zoom + m.pan } pub fn screen_radius(&self, m: &Metadata) -> f32 { self.radius * m.zoom } pub fn visible(&self) -> bool { !self.subfolded } pub fn subselected(&self) -> bool { self.subselected_child || self.subselected_parent } pub fn radius(&self) -> f32 { self.radius } pub(crate) fn set_radius(&mut self, radius: f32) { self.radius = radius; } pub fn subfolded(&self) -> bool { self.subfolded } pub(crate) fn set_subfolded(&mut self, subfolded: bool) { self.subfolded = subfolded; } pub fn subselected_child(&self) -> bool { self.subselected_child } pub(crate) fn set_subselected_child(&mut self, subselected_child: bool) { self.subselected_child = subselected_child; } pub fn subselected_parent(&self) -> bool { self.subselected_parent } pub(crate) fn set_subselected_parent(&mut self, subselected_parent: bool) { self.subselected_parent = subselected_parent; } pub fn data(&self) -> Option<&N> { self.data.as_ref() } pub fn set_data(&mut self, data: Option) { self.data = data; } pub fn with_data(&self, data: Option) -> Self { let mut res = self.clone(); res.data = data; res } pub fn location(&self) -> Vec2 { self.location } pub fn set_location(&mut self, loc: Vec2) { self.location = loc } pub fn folded(&self) -> bool { self.folded } pub fn set_folded(&mut self, folded: bool) { self.folded = folded; } pub fn selected(&self) -> bool { self.selected } pub fn set_selected(&mut self, selected: bool) { self.selected = selected; } pub fn dragged(&self) -> bool { self.dragged } pub fn set_dragged(&mut self, dragged: bool) { self.dragged = dragged; } pub fn label(&self) -> Option<&String> { self.label.as_ref() } pub fn with_label(&mut self, label: String) -> Self { let mut res = self.clone(); res.label = Some(label); res } } ``` -------------------------------- ### Rustdoc Search Tricks Source: https://docs.rs/egui_graphs/0.9.0/help This section details advanced search functionalities within rustdoc. It explains how to filter searches by item kind (e.g., `fn:`, `mod:`), search by type signature, use exact name matching with quotes, search for slice/array types, and search within specific paths. ```Rustdoc Prefix searches with a type followed by a colon (e.g., `fn:`) to restrict the search to a given item kind. Accepted kinds are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`. Search functions by type signature (e.g., `vec -> usize` or `-> vec` or `String, enum:Cow -> bool`) You can look for items with an exact name by putting double quotes around your request: `"string"` Look for functions that accept or return slices and arrays by writing square brackets (e.g., `-> [u8]` or `[] -> Option`) Look for items inside another one by searching for a path: `vec::Vec` ``` -------------------------------- ### Draw Node with Labels and Highlights (Rust) Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/draw/drawer Demonstrates drawing a node with a circular highlight and potentially displaying a label indicating the number of folded sub-nodes. It uses egui's `Layers` and shape primitives like `CircleShape` and `TextShape`. Dependencies include `egui` types like `Pos2`, `Color32`, `Stroke`, `FontId`, and `Vec2`. ```rust let shape = CircleShape { center: loc, radius: node_radius, fill: color_fill, stroke, }; l.add_bottom(shape); let show_label = self.settings_style.labels_always || node.selected() || comp_node.subselected() || node.dragged() || node.folded(); if show_label { if let Some(shape_label) = self.shape_label(node_radius, loc, node) { l.add_bottom(shape_label); } } } fn draw_node_interacted( &self, l: &mut Layers, loc: Pos2, node: &Node, comp_node: &StateComputedNode, ) { let rad = comp_node.radius; let highlight_radius = rad * 1.5; let text_size = rad / 2.; let color_stroke = self .settings_style .color_node_fill(self.p.ctx(), node, comp_node); let shape_highlight_outline = CircleShape { center: loc, radius: highlight_radius, fill: Color32::TRANSPARENT, stroke: Stroke::new(rad, color_stroke), }; l.add_top(shape_highlight_outline); if node.folded() { let galley = self.p.layout_no_wrap( comp_node.num_folded.to_string(), FontId::monospace(text_size), self.settings_style.color_label(self.p.ctx()), ); let galley_offset = rad / 4.; let galley_pos = Pos2::new(loc.x - galley_offset, loc.y - galley_offset); let shape_galley = TextShape::new(galley_pos, galley); l.add_top(shape_galley); } } } ``` -------------------------------- ### Configure GraphView Interactions Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/graph_view Makes the GraphView widget interactive according to the provided settings. This allows customization of how users interact with the graph elements. ```rust /// Makes widget interactive according to the provided settings. pub fn with_interactions(mut self, settings_interaction: &SettingsInteraction) -> Self { self.settings_interaction = settings_interaction.clone(); self } ``` -------------------------------- ### Import Necessary Types Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/draw/drawer Imports various types and constants from the `std` library and the `egui` crate, as well as custom types from the `crate` module, required for graph drawing operations. ```Rust use std::{collections::HashMap, f32::consts::PI}; use egui::{ epaint::{CircleShape, CubicBezierShape, QuadraticBezierShape, TextShape}, Color32, FontFamily, FontId, Painter, Pos2, Shape, Stroke, Vec2, }; use petgraph::{ stable_graph::{EdgeIndex, NodeIndex}, EdgeType, }; use crate::{ settings::SettingsStyle, state_computed::{StateComputed, StateComputedEdge, StateComputedNode}, Edge, Graph, Node, }; use super::layers::Layers; ``` -------------------------------- ### StateComputedNode::new Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/state_computed Creates a new `StateComputedNode` instance, initializing its properties from a given `Node`. Default values are used for selection and folding states. ```Rust impl StateComputedNode { pub fn new(n: &Node) -> Self { Self { radius: DEFAULT_NODE_RADIUS, location: n.location(), selected_child: Default::default(), selected_parent: Default::default(), folded_child: Default::default(), num_folded: Default::default(), } } } ``` -------------------------------- ### GraphView Widget for egui Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/graph_view Implements the egui::Widget trait for the GraphView struct, enabling its use within egui UIs. It handles user interactions like clicking and dragging, computes graph states, and manages navigation and drawing. ```Rust use crossbeam::channel::Sender; use egui::{Pos2, Rect, Response, Sense, Ui, Vec2, Widget}; use petgraph::{stable_graph::NodeIndex, EdgeType}; use crate::{ change::{Change, ChangeNode, ChangeSubgraph}, metadata::Metadata, settings::SettingsNavigation, settings::{SettingsInteraction, SettingsStyle}, state_computed::StateComputed, Drawer, Graph, }; /// Widget for visualizing and interacting with graphs. /// /// It implements [egui::Widget] and can be used like any other widget. /// /// The widget uses a mutable reference to the [StableGraph, egui_graphs::Edge>] /// struct to visualize and interact with the graph. `N` and `E` is arbitrary client data associated with nodes and edges. /// You can customize the visualization and interaction behavior using [SettingsInteraction], [SettingsNavigation] and [SettingsStyle] structs. /// /// When any interaction or node property change occurs, the widget sends [Change] struct to the provided /// [Sender] channel, which can be set via the `with_interactions` method. The [Change] struct contains information about /// a change that occurred in the graph. Client can use this information to modify external state of his application if needed. /// /// When the user performs navigation actions (zoom & pan, fit to screen), they do not /// produce changes. This is because these actions are performed on the global coordinates and do not change any /// properties of the nodes or edges. pub struct GraphView<'a, N: Clone, E: Clone, Ty: EdgeType> { settings_interaction: SettingsInteraction, settings_navigation: SettingsNavigation, settings_style: SettingsStyle, g: &'a mut Graph, changes_sender: Option<&'a Sender>, } impl<'a, N: Clone, E: Clone, Ty: EdgeType> Widget for &mut GraphView<'a, N, E, Ty> { fn ui(self, ui: &mut Ui) -> Response { let (resp, p) = ui.allocate_painter(ui.available_size(), Sense::click_and_drag()); let mut meta = Metadata::get(ui); let mut computed = self.compute_computed(&meta); self.handle_fit_to_screen(&resp, &mut meta, &computed); self.handle_navigation(ui, &resp, &mut meta, &computed); self.handle_node_drag(&resp, &mut computed, &mut meta); self.handle_click(&resp, &mut computed, &mut meta); Drawer::new(p, self.g, &computed, &self.settings_style).draw(); meta.store_into_ui(ui); ``` -------------------------------- ### Transform to Graph with Custom Logic (Rust) Source: https://docs.rs/egui_graphs/0.9.0/egui_graphs/index Similar to `to_graph`, but allows defining custom transformation procedures for nodes and edges. This offers greater flexibility in graph data conversion. ```Rust pub fn to_graph_custom(graph: petgraph::stable_graph::StableGraph, node_transform: FN, edge_transform: FE) -> Graph where FN: Fn(petgraph::stable_graph::NodeIndex, &N) -> (N, egui_graphs::SettingsNode), FE: Fn(petgraph::stable_graph::EdgeIndex, &E) -> (E, egui_graphs::SettingsEdge), ``` -------------------------------- ### Rust: Compare `roots` and `roots_by_node` Methods Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/subgraphs This Rust code snippet verifies the consistency between the `roots` method and the `roots_by_node` method in the `SubGraphs` struct. It adds subgraphs, collects all roots using both methods, and asserts that the results are identical after deduplication. ```rust let g = create_test_graph(); let graph = Graph::new(g); let mut subgraphs = SubGraphs::default(); // a->b, a->d subgraphs.add_subgraph(&graph, NodeIndex::new(0), 1); // b->c subgraphs.add_subgraph(&graph, NodeIndex::new(1), 1); let all_roots_from_roots_by_node = subgraphs .roots_by_node .values() .cloned() .reduce(|acc, el| acc.into_iter().chain(el.into_iter()).collect()) .unwrap(); let all_roots_from_roots_by_node_deduped = all_roots_from_roots_by_node.iter().collect::>(); assert_eq!( subgraphs.roots().len(), all_roots_from_roots_by_node_deduped.len() ); subgraphs.roots().iter().for_each(|root| { assert!(all_roots_from_roots_by_node_deduped.contains(root)); }); ``` -------------------------------- ### Fit Graph to Screen in Rust Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/graph_view Calculates and applies zoom and pan transformations to fit the entire graph within the visible screen area, including decorative padding. Handles empty or single-node graphs with default sizing. ```rust fn fit_to_screen(&self, rect: &Rect, meta: &mut Metadata, comp: &StateComputed) { // calculate graph dimensions with decorative padding let mut diag = comp.graph_bounds.max - comp.graph_bounds.min; // if the graph is empty or consists from one node, use a default size if diag == Vec2::ZERO { diag = Vec2::new(1., 100.); } let graph_size = diag * (1. + self.settings_navigation.screen_padding); let (width, height) = (graph_size.x, graph_size.y); // calculate canvas dimensions let canvas_size = rect.size(); let (canvas_width, canvas_height) = (canvas_size.x, canvas_size.y); // calculate zoom factors for x and y to fit the graph inside the canvas let zoom_x = canvas_width / width; let zoom_y = canvas_height / height; // choose the minimum of the two zoom factors to avoid distortion let new_zoom = zoom_x.min(zoom_y); // calculate the zoom delta and call handle_zoom to adjust the zoom factor let zoom_delta = new_zoom / meta.zoom - 1.0; self.zoom(rect, zoom_delta, None, meta); // calculate the center of the graph and the canvas let graph_center = (comp.graph_bounds.min.to_vec2() + comp.graph_bounds.max.to_vec2()) / 2.0; // adjust the pan value to align the centers of the graph and the canvas meta.pan = rect.center().to_vec2() - graph_center * new_zoom; } ``` -------------------------------- ### Rust TryFrom and TryInto Conversions Source: https://docs.rs/egui_graphs/0.9.0/egui_graphs/struct Enables fallible type conversions using TryFrom and TryInto traits. It defines the error type for conversions and provides methods for attempting conversions, returning a Result. ```Rust type Error = Infallible fn try_from(value: U) -> Result>::Error> type Error = >::Error fn try_into(self) -> Result>::Error> ``` -------------------------------- ### Rust: Add and Verify Subgraph Properties Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/subgraphs This Rust code snippet demonstrates how to add a subgraph to a graph using the `add_subgraph` method and then verifies its properties, such as node and edge counts. It uses `NodeIndex` for node identification and `assert_eq!` for validation. ```rust subgraphs.add_subgraph(&graph, NodeIndex::new(0), 0); assert_eq!(subgraphs.data.len(), 1); let subgraph = subgraphs.data.get(&NodeIndex::new(0)).unwrap(); assert_eq!(subgraph.node_count(), 0); assert_eq!(subgraph.edge_count(), 0); ``` -------------------------------- ### Fill Edge Layers Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/draw/drawer Populates layers with edge information. It iterates through all edges, determines their source and target nodes, and organizes them into a map based on node pairs for efficient rendering. ```Rust fn fill_layers_edges(&self, l: &mut Layers) { let mut edge_map: EdgeMap = HashMap::new(); self.g.edges_iter().for_each(|(idx, e)| { let (source, target) = self.g.edge_endpoints(idx).unwrap(); // compute map with edges between 2 nodes edge_map .entry((source, target)) .or_insert_with(Vec::new) ``` -------------------------------- ### StateComputedEdge::new Source: https://docs.rs/egui_graphs/0.9.0/src/egui_graphs/state_computed Creates a new `StateComputedEdge` instance, initializing its properties from a given `Edge`. Default values are used for selection states. ```Rust impl StateComputedEdge { pub fn new(e: &Edge) -> Self { Self { width: e.width(), tip_size: e.tip_size(), curve_size: e.curve_size(), selected_child: Default::default(), selected_parent: Default::default(), } } } ``` -------------------------------- ### Implement StructuralPartialEq for StateComputedNode Source: https://docs.rs/egui_graphs/0.9.0/egui_graphs/struct Indicates that StateComputedNode implements StructuralPartialEq, which allows for structural equality comparisons. ```Rust source ```