#[macro_use] extern crate conrod_core;
extern crate conrod_glium;
extern crate conrod_winit;
extern crate find_folder;
extern crate glium;
extern crate petgraph;
mod support;
use conrod_core::{widget, Borderable, Colorable, Labelable, Positionable, Sizeable, Widget};
use conrod_core::widget::graph::{node, Event, EdgeEvent, Node, NodeEvent, NodeSocket};
use glium::Surface;
use std::collections::HashMap;
widget_ids! {
struct Ids {
graph,
}
}
type MyGraph = petgraph::Graph<&'static str, (usize, usize)>;
type Layout = widget::graph::Layout<petgraph::graph::NodeIndex>;
fn main() {
const WIDTH: u32 = 900;
const HEIGHT: u32 = 500;
let mut graph = MyGraph::new();
let a = graph.add_node("A");
let b = graph.add_node("B");
let c = graph.add_node("C");
let d = graph.add_node("D");
let e = graph.add_node("E");
graph.extend_with_edges(&[
(a, c, (1, 0)),
(a, d, (0, 1)),
(b, d, (0, 0)),
(c, d, (0, 2)),
(d, e, (0, 0)),
]);
let mut layout_map = HashMap::new();
layout_map.insert(b, [-100.0, 100.0]);
layout_map.insert(a, [-300.0, 0.0]);
layout_map.insert(c, [-100.0, -100.0]);
layout_map.insert(d, [100.0, 0.0]);
layout_map.insert(e, [300.0, 0.0]);
let mut layout = Layout::from(layout_map);
let mut events_loop = glium::glutin::EventsLoop::new();
let window = glium::glutin::WindowBuilder::new()
.with_title("Conrod Graph Widget")
.with_dimensions((WIDTH, HEIGHT).into());
let context = glium::glutin::ContextBuilder::new()
.with_multisampling(4)
.with_vsync(true);
let display = glium::Display::new(window, context, &events_loop).unwrap();
let display = support::GliumDisplayWinitWrapper(display);
let mut ui = conrod_core::UiBuilder::new([WIDTH as f64, HEIGHT as f64]).build();
let ids = Ids::new(ui.widget_id_generator());
let assets = find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap();
let font_path = assets.join("fonts/NotoSans/NotoSans-Regular.ttf");
ui.fonts.insert_from_file(font_path).expect("Couldn't load font");
let mut renderer = conrod_glium::Renderer::new(&display.0).unwrap();
let image_map = conrod_core::image::Map::<glium::texture::Texture2d>::new();
let mut event_loop = support::EventLoop::new();
'main: loop {
for event in event_loop.next(&mut events_loop) {
if let Some(event) = conrod_winit::convert_event(event.clone(), &display) {
ui.handle_event(event);
event_loop.needs_update();
}
match event.clone() {
glium::glutin::Event::WindowEvent { event, .. } => {
match event {
glium::glutin::WindowEvent::CloseRequested |
glium::glutin::WindowEvent::KeyboardInput {
input: glium::glutin::KeyboardInput {
virtual_keycode: Some(glium::glutin::VirtualKeyCode::Escape),
..
},
..
} => break 'main,
_ => (),
}
}
_ => (),
}
}
set_widgets(&mut ui.set_widgets(), &ids, &mut graph, &mut layout);
if let Some(primitives) = ui.draw_if_changed() {
renderer.fill(&display.0, primitives, &image_map);
let mut target = display.0.draw();
target.clear_color(0.0, 0.0, 0.0, 1.0);
renderer.draw(&display.0, &mut target, &image_map).unwrap();
target.finish().unwrap();
}
}
}
fn set_widgets(ui: &mut conrod_core::UiCell, ids: &Ids, graph: &mut MyGraph, layout: &mut Layout) {
let session = {
let node_indices = graph.node_indices();
let edges = graph.raw_edges()
.iter()
.map(|e| {
let start = NodeSocket { id: e.source(), socket_index: e.weight.0 };
let end = NodeSocket { id: e.target(), socket_index: e.weight.1 };
(start, end)
});
widget::Graph::new(node_indices, edges, layout)
.background_color(conrod_core::color::rgb(0.31, 0.33, 0.35))
.wh_of(ui.window)
.middle_of(ui.window)
.set(ids.graph, ui)
};
for event in session.events() {
match event {
Event::Node(event) => match event {
NodeEvent::Remove(node_id) => {
},
NodeEvent::Dragged { node_id, to, .. } => {
*layout.get_mut(&node_id).unwrap() = to;
},
},
Event::Edge(event) => match event {
EdgeEvent::AddStart(node_socket) => {
},
EdgeEvent::Add { start, end } => {
},
EdgeEvent::Cancelled(node_socket) => {
},
EdgeEvent::Remove { start, end } => {
},
},
}
}
let mut session = session.next();
for node in session.nodes() {
let node_id = node.node_id();
let inputs = graph.neighbors_directed(node_id, petgraph::Incoming).count();
let outputs = graph.neighbors_directed(node_id, petgraph::Outgoing).count();
let button = widget::Button::new()
.label(&graph[node_id])
.border(0.0);
let widget = Node::new(button)
.inputs(inputs)
.outputs(outputs)
.w_h(100.0, 60.0);
for _click in node.widget(widget).set(ui).widget_event {
println!("{} was clicked!", &graph[node_id]);
}
}
let mut session = session.next();
for edge in session.edges() {
let (a, b) = node::edge_socket_rects(&edge, ui);
let line = widget::Line::abs(a.xy(), b.xy())
.color(conrod_core::color::DARK_CHARCOAL)
.thickness(3.0);
edge.widget(line).set(ui);
}
}