Turn view::port::Port into a gtk::Button subclass

This commit is contained in:
Tom A. Wagner
2021-04-02 14:53:58 +02:00
parent 9b448f0a30
commit 75aa0a30d0
3 changed files with 56 additions and 28 deletions

View File

@@ -137,7 +137,7 @@ mod imp {
// For some reason, gtk4::WidgetExt::translate_coordinates gives me incorrect values, // For some reason, gtk4::WidgetExt::translate_coordinates gives me incorrect values,
// so we manually calculate the needed offsets here. // so we manually calculate the needed offsets here.
let from_port = &nodes.get(&link.node_from)?.get_port(link.port_from)?.widget; let from_port = &nodes.get(&link.node_from)?.get_port(link.port_from)?;
let gtk::Allocation { let gtk::Allocation {
x: mut fx, x: mut fx,
y: mut fy, y: mut fy,
@@ -151,7 +151,7 @@ mod imp {
fx += fnx + fw; fx += fnx + fw;
fy += fny + (fh / 2); fy += fny + (fh / 2);
let to_port = &nodes.get(&link.node_to)?.get_port(link.port_to)?.widget; let to_port = &nodes.get(&link.node_to)?.get_port(link.port_to)?;
let gtk::Allocation { let gtk::Allocation {
x: mut tx, x: mut tx,
y: mut ty, y: mut ty,

View File

@@ -108,21 +108,17 @@ impl Node {
pub fn add_port(&mut self, id: u32, port: super::port::Port) { pub fn add_port(&mut self, id: u32, port: super::port::Port) {
let private = imp::Node::from_instance(self); let private = imp::Node::from_instance(self);
match port.direction { match port.direction() {
Direction::Input => { Direction::Input => {
private private
.grid .grid
.attach(&port.widget, 0, private.num_ports_in.get() as i32 + 1, 1, 1); .attach(&port, 0, private.num_ports_in.get() as i32 + 1, 1, 1);
private.num_ports_in.set(private.num_ports_in.get() + 1); private.num_ports_in.set(private.num_ports_in.get() + 1);
} }
Direction::Output => { Direction::Output => {
private.grid.attach( private
&port.widget, .grid
1, .attach(&port, 1, private.num_ports_out.get() as i32 + 1, 1, 1);
private.num_ports_out.get() as i32 + 1,
1,
1,
);
private.num_ports_out.set(private.num_ports_out.get() + 1); private.num_ports_out.set(private.num_ports_out.get() + 1);
} }
} }
@@ -138,12 +134,12 @@ impl Node {
pub fn remove_port(&self, id: u32) { pub fn remove_port(&self, id: u32) {
let private = imp::Node::from_instance(self); let private = imp::Node::from_instance(self);
if let Some(port) = private.ports.borrow_mut().remove(&id) { if let Some(port) = private.ports.borrow_mut().remove(&id) {
match port.direction { match port.direction() {
Direction::Input => private.num_ports_in.set(private.num_ports_in.get() - 1), Direction::Input => private.num_ports_in.set(private.num_ports_in.get() - 1),
Direction::Output => private.num_ports_in.set(private.num_ports_out.get() - 1), Direction::Output => private.num_ports_in.set(private.num_ports_out.get() - 1),
} }
port.widget.unparent(); port.unparent();
} }
} }
} }

View File

@@ -1,12 +1,34 @@
use gtk::WidgetExt; use gtk::{glib, prelude::*, subclass::prelude::*};
use crate::controller::MediaType; use crate::controller::MediaType;
mod imp {
use once_cell::unsync::OnceCell;
use super::*;
/// Graphical representation of a pipewire port. /// Graphical representation of a pipewire port.
#[derive(Default)]
pub struct Port { pub struct Port {
pub widget: gtk::Button, pub(super) id: OnceCell<u32>,
pub id: u32, pub(super) direction: OnceCell<pipewire::port::Direction>,
pub direction: pipewire::port::Direction, }
#[glib::object_subclass]
impl ObjectSubclass for Port {
const NAME: &'static str = "Port";
type Type = super::Port;
type ParentType = gtk::Button;
}
impl ObjectImpl for Port {}
impl WidgetImpl for Port {}
impl ButtonImpl for Port {}
}
glib::wrapper! {
pub struct Port(ObjectSubclass<imp::Port>)
@extends gtk::Button, gtk::Widget;
} }
impl Port { impl Port {
@@ -16,20 +38,30 @@ impl Port {
direction: pipewire::port::Direction, direction: pipewire::port::Direction,
media_type: Option<MediaType>, media_type: Option<MediaType>,
) -> Self { ) -> Self {
let widget = gtk::Button::with_label(name); // Create the widget and initialize needed fields
let res: Self = glib::Object::new(&[]).expect("Failed to create Port");
let private = imp::Port::from_instance(&res);
private.id.set(id).expect("Port id already set");
private
.direction
.set(direction)
.expect("Port direction already set");
res.set_child(Some(&gtk::Label::new(Some(name))));
// Color the port according to its media type. // Color the port according to its media type.
match media_type { match media_type {
Some(MediaType::Video) => widget.add_css_class("video"), Some(MediaType::Video) => res.add_css_class("video"),
Some(MediaType::Audio) => widget.add_css_class("audio"), Some(MediaType::Audio) => res.add_css_class("audio"),
Some(MediaType::Midi) => widget.add_css_class("midi"), Some(MediaType::Midi) => res.add_css_class("midi"),
None => {} None => {}
} }
Self { res
widget, }
id,
direction, pub fn direction(&self) -> &pipewire::port::Direction {
} let private = imp::Port::from_instance(self);
private.direction.get().expect("Port direction is not set")
} }
} }