network_graph 0.1.0

Network-style graph utilities and egui widget
Documentation
use eframe::egui;
use egui::pos2;
use egui_network_map::{EdgeData, GraphWidget, NodeData};
use uuid::Uuid;

const DEPTH: u32 = 5;
const CANVAS_WIDTH: f32 = 1000.0;

pub struct BasicNode;

impl NodeData for BasicNode {}

pub struct BasicEdge;

impl EdgeData<BasicNode> for BasicEdge {}

fn main() -> eframe::Result<()> {
    let options = eframe::NativeOptions {
        run_and_return: true,
        viewport: egui::ViewportBuilder::default().with_inner_size([800.0, 800.0]),
        ..Default::default()
    };

    let mut graph: GraphWidget<BasicNode, BasicEdge> = GraphWidget::default();

    let depth_change = CANVAS_WIDTH / DEPTH as f32;

    recurse(&mut graph, depth_change, None, 0, 0);

    eframe::run_native(
        "First window",
        options.clone(),
        Box::new(|_cc| Ok(Box::new(ExampleApp { graph }))),
    )?;

    return Ok(());
}

fn recurse(
    graph: &mut GraphWidget<BasicNode, BasicEdge>,
    depth_variation: f32,
    root_uuid: Option<Uuid>,
    layer: u32,
    x_pos: usize,
) {
    if layer >= DEPTH {
        return;
    }

    let x_spacing = CANVAS_WIDTH / ((2 as i32).pow(layer) + 1) as f32;
    let x_coord = CANVAS_WIDTH / -2.0 + x_spacing * (x_pos + 1) as f32;
    let y_coord = CANVAS_WIDTH / -2.0 + depth_variation * layer as f32;
    let uuid = graph.new_node(BasicNode, pos2(x_coord, y_coord));
    if let Some(root_uuid) = root_uuid {
        graph.new_connection(BasicEdge, root_uuid, uuid);
    }

    recurse(graph, depth_variation, Some(uuid), layer + 1, x_pos * 2);

    recurse(graph, depth_variation, Some(uuid), layer + 1, x_pos * 2 + 1);
}

struct ExampleApp {
    graph: GraphWidget<BasicNode, BasicEdge>,
}

impl eframe::App for ExampleApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| ui.add(&mut self.graph));
    }
}