facett-graphnav V.G — guide
Class:
guide· the how-to for the elevated GRAPH NAVIGATOR. Concepts:graphnav-vg-design.md. Beginner walkthrough:graphnav-vg-for-idiots.md.
Build one
use facett_graphnav::{GraphNav, Msg, LayoutKind, Metric, Partition, ExportFormat};
let mut nav = GraphNav::demo(); // or GraphNav::new("title", my_prop_graph)
GraphNav is a facett_core::Facet — drop it in a deck, or drive it headlessly by folding Msgs and reading nav.state_json().
Navigate (the camera)
Drag to pan, scroll to zoom on the canvas. Programmatically / from a robot:
nav.update(Msg::CameraZoom(1.5)); // scroll-zoom in (clamped 0.25..4.0)
nav.update(Msg::CameraPan([0.2, -0.1])); // pan in world units
nav.update(Msg::FitView); // ⊙ fit — reset pan+zoom
nav.update(Msg::SelectNode("p3".into()));
nav.update(Msg::ZoomToSelection); // ⊹ focus — centre + zoom the selection
let cam = nav.state_json()["camera"]; // { pan:[x,y], zoom }
Toolbar buttons ⊙ fit / ⊹ focus do the same. Labels fade in as you zoom past 1.6×; hovering a node dims the rest and highlights its neighbourhood.
Encode data as appearance (ranking + partition)
Size and colour are three independent channels:
nav.update(Msg::SetSizeBy(Some(Metric::Degree))); // node radius ∝ degree
nav.update(Msg::SetColorMetric(Some(Metric::PageRank))); // sequential ramp (low→high)
nav.update(Msg::SetPartition(Some(Partition::Louvain))); // categorical hue by community
- Metrics (size or colour):
Degree,PageRank,Betweenness,Closeness,Eigenvector,KCore. - Partitions (colour):
Louvain,Label,Component. - Colour precedence: partition > continuous metric > the categorical
StyleBy. Setting a partition clears the ramp and vice-versa. - Pass
Noneto any channel to turn it off. Edge thickness follows aweightproperty automatically.
In the UI: the size: / ramp: / partition: toolbar row. Read it back at state_json.appearance (size_by, color_mode, partition_count) and per-node radius/color under canvas.nodes.
Open the data-laboratory table
let node_batch = nav.node_batch(); // Arrow RecordBatch: id,label,caption,degree,pagerank,betweenness,community
let edge_batch = nav.edge_batch(); // Arrow RecordBatch: src,dst,type,weight
let grid = facett_grid::Grid::from_record_batch("nodes", &node_batch);
Two-way selection sync is a plain row↔index map:
if let Some(msg) = nav.select_node_row(3) { nav.update(msg); } // grid → canvas
let row = nav.selected_node_row(); // canvas → grid
Import / export (Gephi's front door)
let gexf = nav.export(ExportFormat::Gexf); // also GraphMl / Json / Dot / Csv
let back = GraphNav::import("in", ExportFormat::Gexf, &gexf)?; // GraphMl / Json too
GEXF/GraphML carry the label + properties + computed metrics (degree, pagerank, betweenness, Louvain community) as attributes. Import is tolerant of the XML Gephi / NetworkX / yEd emit. DOT/CSV are write-only (import returns Err).
Read the stats
let s = nav.stats(); // also at state_json.stats
// { nodes, edges, density, avg_degree, components, largest_component,
// modularity, communities, avg_clustering, transitivity, diameter, avg_path_length }
The 📊 stats collapsible panel shows the same scalars.
In facett-demo
Run the demo and open the V.G tab. Toggle 🖈 canvas / ▦ table. The tab is driven by the Swedish population graph; a robot drive lives in facett-demo/tests/vg_lab.rs.