network_graph 0.1.2

Network-style graph utilities and egui widget
Documentation
use eframe::egui;
use env_logger::Builder;
use network_graph::{
    self,
    graph::Graph,
    widget::{EdgeEntry, GraphWidget, NodeEntry, Pos2},
};

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

fn main() -> eframe::Result<()> {
    Builder::new()
        .filter_module("network_graph::widget", log::LevelFilter::Trace)
        .init();

    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<usize, usize> = 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<usize, usize>,
    depth_variation: f32,
    root_uuid: Option<usize>,
    layer: u32,
    x_pos: usize,
) {
    if layer >= DEPTH {
        return;
    }

    // Calculate node and upward edges uid.
    let layer_n = layer as usize + 1;
    let layer_start = (layer_n * (layer_n + 1) / 2) - 1;
    let id = layer_start + x_pos;

    let x_spacing = CANVAS_WIDTH / ((2 as i32).pow(layer) + 1) as f32;
    let x = CANVAS_WIDTH / -2.0 + x_spacing * (x_pos + 1) as f32;
    let y = CANVAS_WIDTH / -2.0 + depth_variation * layer as f32;
    let pos = Pos2::new(x, y);

    graph.insert_node(NodeEntry {
        id,
        pos,
        style: Default::default(),
    });

    if let Some(root_id) = root_uuid {
        graph
            .insert_edge(EdgeEntry {
                id,
                style: Default::default(),
                ends: [id, root_id],
            })
            .unwrap();
    }

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

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

struct ExampleApp {
    graph: GraphWidget<usize, usize>,
}

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));
        self.graph.modify_canvas().default_interact();
        self.graph
            .modify_interacted_nodes(|mut ctx| ctx.default_interact());
    }
}