Add initial project.

This commit is contained in:
Tom A. Wagner
2020-11-11 12:44:17 +01:00
commit 264ccf0982
7 changed files with 891 additions and 0 deletions

96
src/view/graph_view.rs Normal file
View File

@@ -0,0 +1,96 @@
use super::PipewireNode;
use cairo::Context;
use glib::clone;
use gtk::{prelude::*, LayoutExt};
use std::{cell::RefCell, collections::HashMap, rc::Rc};
pub struct GraphView {
pub(crate) widget: gtk::Layout,
nodes: Rc<RefCell<HashMap<u32, PipewireNode>>>,
links: Rc<RefCell<HashMap<u32, crate::PipewireLink>>>,
}
impl GraphView {
pub fn new() -> Self {
let result = Self {
widget: gtk::Layout::new::<gtk::Adjustment, gtk::Adjustment>(None, None),
nodes: Rc::new(RefCell::new(HashMap::new())),
links: Rc::new(RefCell::new(HashMap::new())),
};
result.widget.connect_draw(clone!(
@weak result.nodes as nodes, @weak result.links as links => @default-panic,
move |_, cr| {
draw(nodes, links, cr);
Inhibit(false)
}));
result
}
pub fn add_node(&mut self, id: u32, node: PipewireNode) {
// TODO: Find a free position to put the widget at.
self.widget.put(
&node.widget,
(self.nodes.borrow().len() % 4 * 400) as i32,
(self.nodes.borrow().len() / 4 * 100) as i32,
);
self.nodes.borrow_mut().insert(id, node);
}
/// Add a link to the graph.
///
/// `add_link` takes three arguments: `link_id` is the id of the link as assigned by the pipewire server,
/// `from` and `to` are the id's of the ingoing and outgoing port, respectively.
pub fn add_link(&mut self, link_id: u32, link: crate::PipewireLink) {
self.links.borrow_mut().insert(link_id, link);
self.widget.queue_draw();
}
}
fn draw(
nodes: Rc<RefCell<HashMap<u32, PipewireNode>>>,
links: Rc<RefCell<HashMap<u32, crate::PipewireLink>>>,
cr: &Context,
) {
cr.set_line_width(2.0);
cr.set_source_rgb(255.0, 255.0, 255.0);
cr.paint();
cr.set_source_rgb(0.0, 0.0, 0.0);
for link in links.borrow().values() {
let (from_alloc, to_alloc) = get_allocs(nodes.clone(), link);
cr.move_to(
(from_alloc.x + from_alloc.width).into(),
(from_alloc.y + (from_alloc.height / 2)).into()
);
cr.line_to(
to_alloc.x.into(),
(to_alloc.y + (to_alloc.height / 2)).into()
);
cr.stroke();
}
}
fn get_allocs(
nodes: Rc<RefCell<HashMap<u32, PipewireNode>>>,
link: &crate::PipewireLink,
) -> (gtk::Allocation, gtk::Allocation) {
let from_alloc = &nodes
.borrow()
.get(&link.node_from)
.unwrap()
.get_outgoing_port(link.port_from)
.unwrap()
.get_allocation();
let to_alloc = &nodes
.borrow()
.get(&link.node_to)
.unwrap()
.get_ingoing_port(link.port_to)
.unwrap()
.get_allocation();
(from_alloc.to_owned(), to_alloc.to_owned())
}

5
src/view/mod.rs Normal file
View File

@@ -0,0 +1,5 @@
mod graph_view;
mod pipewire_node;
pub use pipewire_node::PipewireNode;
pub use graph_view::GraphView;

43
src/view/pipewire_node.rs Normal file
View File

@@ -0,0 +1,43 @@
use gtk::GridExt;
use std::collections::HashMap;
pub struct PipewireNode {
pub(super) widget: gtk::Grid,
_label: gtk::Label,
ingoing_ports: HashMap<u32, gtk::Button>,
outgoing_ports: HashMap<u32, gtk::Button>,
}
impl PipewireNode {
pub fn new(name: &str) -> Self {
let widget = gtk::Grid::new();
let label = gtk::Label::new(Some(name));
widget.attach(&label, 0, 0, 2, 1);
Self {
widget,
_label: label,
ingoing_ports: HashMap::new(),
outgoing_ports: HashMap::new(),
}
}
pub fn add_ingoing_port(&mut self, id: u32, port: gtk::Button) {
self.widget.attach(&port, 0, (self.ingoing_ports.len() + 1) as i32, 1, 1);
self.ingoing_ports.insert(id, port);
}
pub fn add_outgoing_port(&mut self, id: u32, port: gtk::Button) {
self.widget.attach(&port, 1, (self.outgoing_ports.len() + 1) as i32, 1, 1);
self.outgoing_ports.insert(id, port);
}
pub fn get_ingoing_port(&self, id: u32) -> Option<&gtk::Button> {
self.ingoing_ports.get(&id)
}
pub fn get_outgoing_port(&self, id: u32) -> Option<&gtk::Button> {
self.outgoing_ports.get(&id)
}
}