From 75aa0a30d0af0ebae81bdf03de5f9c8e6081dcbb Mon Sep 17 00:00:00 2001 From: "Tom A. Wagner" Date: Fri, 2 Apr 2021 14:53:58 +0200 Subject: [PATCH] Turn view::port::Port into a gtk::Button subclass --- src/view/graph_view.rs | 4 +-- src/view/node.rs | 18 +++++------- src/view/port.rs | 62 ++++++++++++++++++++++++++++++++---------- 3 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/view/graph_view.rs b/src/view/graph_view.rs index d18c456..75690c7 100644 --- a/src/view/graph_view.rs +++ b/src/view/graph_view.rs @@ -137,7 +137,7 @@ mod imp { // For some reason, gtk4::WidgetExt::translate_coordinates gives me incorrect values, // 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 { x: mut fx, y: mut fy, @@ -151,7 +151,7 @@ mod imp { fx += fnx + fw; 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 { x: mut tx, y: mut ty, diff --git a/src/view/node.rs b/src/view/node.rs index 9c8b607..74fa214 100644 --- a/src/view/node.rs +++ b/src/view/node.rs @@ -108,21 +108,17 @@ impl Node { pub fn add_port(&mut self, id: u32, port: super::port::Port) { let private = imp::Node::from_instance(self); - match port.direction { + match port.direction() { Direction::Input => { private .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); } Direction::Output => { - private.grid.attach( - &port.widget, - 1, - private.num_ports_out.get() as i32 + 1, - 1, - 1, - ); + private + .grid + .attach(&port, 1, private.num_ports_out.get() as i32 + 1, 1, 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) { let private = imp::Node::from_instance(self); 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::Output => private.num_ports_in.set(private.num_ports_out.get() - 1), } - port.widget.unparent(); + port.unparent(); } } } diff --git a/src/view/port.rs b/src/view/port.rs index e353e0a..9c55b15 100644 --- a/src/view/port.rs +++ b/src/view/port.rs @@ -1,12 +1,34 @@ -use gtk::WidgetExt; +use gtk::{glib, prelude::*, subclass::prelude::*}; use crate::controller::MediaType; -/// Graphical representation of a pipewire port. -pub struct Port { - pub widget: gtk::Button, - pub id: u32, - pub direction: pipewire::port::Direction, +mod imp { + use once_cell::unsync::OnceCell; + + use super::*; + + /// Graphical representation of a pipewire port. + #[derive(Default)] + pub struct Port { + pub(super) id: OnceCell, + pub(super) direction: OnceCell, + } + + #[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) + @extends gtk::Button, gtk::Widget; } impl Port { @@ -16,20 +38,30 @@ impl Port { direction: pipewire::port::Direction, media_type: Option, ) -> 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(>k::Label::new(Some(name)))); // Color the port according to its media type. match media_type { - Some(MediaType::Video) => widget.add_css_class("video"), - Some(MediaType::Audio) => widget.add_css_class("audio"), - Some(MediaType::Midi) => widget.add_css_class("midi"), + Some(MediaType::Video) => res.add_css_class("video"), + Some(MediaType::Audio) => res.add_css_class("audio"), + Some(MediaType::Midi) => res.add_css_class("midi"), None => {} } - Self { - widget, - id, - direction, - } + res + } + + pub fn direction(&self) -> &pipewire::port::Direction { + let private = imp::Port::from_instance(self); + private.direction.get().expect("Port direction is not set") } }