Update gtk and glib dependencies

This commit is contained in:
Tom A. Wagner
2023-02-12 20:21:28 +01:00
parent 4ed52bb00d
commit 146fb65dc5
7 changed files with 205 additions and 248 deletions

View File

@@ -52,7 +52,8 @@ mod imp {
impl ObjectImpl for Application {}
impl ApplicationImpl for Application {
fn activate(&self, app: &Self::Type) {
fn activate(&self) {
let app = &*self.obj();
let scrollwindow = gtk::ScrolledWindow::builder()
.child(&self.graphview)
.build();
@@ -85,12 +86,12 @@ mod imp {
window.show();
}
fn startup(&self, app: &Self::Type) {
self.parent_startup(app);
fn startup(&self) {
self.parent_startup();
// Load CSS from the STYLE variable.
let provider = gtk::CssProvider::new();
provider.load_from_data(STYLE.as_bytes());
provider.load_from_data(STYLE);
gtk::StyleContext::add_provider_for_display(
&gtk::gdk::Display::default().expect("Error initializing gtk css provider."),
&provider,
@@ -114,10 +115,11 @@ impl Application {
gtk_receiver: Receiver<PipewireMessage>,
pw_sender: Sender<GtkMessage>,
) -> Self {
let app: Application = glib::Object::new(&[("application-id", &"org.pipewire.Helvum")])
.expect("Failed to create new Application");
let app: Application = glib::Object::builder()
.property("application-id", &"org.pipewire.Helvum")
.build();
let imp = imp::Application::from_instance(&app);
let imp = app.imp();
imp.pw_sender
.set(RefCell::new(pw_sender))
// Discard the returned sender, as it does not implement `Debug`.
@@ -159,11 +161,9 @@ impl Application {
fn add_node(&self, id: u32, name: &str, node_type: Option<NodeType>) {
info!("Adding node to graph: id {}", id);
imp::Application::from_instance(self).graphview.add_node(
id,
view::Node::new(name, id),
node_type,
);
self.imp()
.graphview
.add_node(id, view::Node::new(name, id), node_type);
}
/// Add a new port to the view.
@@ -177,8 +177,6 @@ impl Application {
) {
info!("Adding port to graph: id {}", id);
let imp = imp::Application::from_instance(self);
let port = view::Port::new(id, name, direction, media_type);
// Create or delete a link if the widget emits the "port-toggled" signal.
@@ -196,7 +194,7 @@ impl Application {
}),
);
imp.graphview.add_port(node_id, id, port);
self.imp().graphview.add_port(node_id, id, port);
}
/// Add a new link to the view.
@@ -214,7 +212,7 @@ impl Application {
// FIXME: Links should be colored depending on the data they carry (video, audio, midi) like ports are.
// Update graph to contain the new link.
imp::Application::from_instance(self).graphview.add_link(
self.imp().graphview.add_link(
id,
PipewireLink {
node_from,
@@ -233,15 +231,17 @@ impl Application {
if active { "active" } else { "inactive" }
);
imp::Application::from_instance(self)
.graphview
.set_link_state(id, active);
self.imp().graphview.set_link_state(id, active);
}
// Toggle a link between the two specified ports on the remote pipewire server.
fn toggle_link(&self, port_from: u32, port_to: u32) {
let imp = imp::Application::from_instance(self);
let sender = imp.pw_sender.get().expect("pw_sender not set").borrow_mut();
let sender = self
.imp()
.pw_sender
.get()
.expect("pw_sender not set")
.borrow_mut();
sender
.send(GtkMessage::ToggleLink { port_from, port_to })
.expect("Failed to send message");
@@ -251,8 +251,7 @@ impl Application {
fn remove_node(&self, id: u32) {
info!("Removing node from graph: id {}", id);
let imp = imp::Application::from_instance(self);
imp.graphview.remove_node(id);
self.imp().graphview.remove_node(id);
}
/// Remove the port with the id `id` from the node with the id `node_id`
@@ -260,15 +259,13 @@ impl Application {
fn remove_port(&self, id: u32, node_id: u32) {
info!("Removing port from graph: id {}, node_id: {}", id, node_id);
let imp = imp::Application::from_instance(self);
imp.graphview.remove_port(id, node_id);
self.imp().graphview.remove_port(id, node_id);
}
/// Remove the link with the specified id from the view.
fn remove_link(&self, id: u32) {
info!("Removing link from graph: id {}", id);
let imp = imp::Application::from_instance(self);
imp.graphview.remove_link(id);
self.imp().graphview.remove_link(id);
}
}

View File

@@ -83,17 +83,17 @@ mod imp {
}
impl ObjectImpl for GraphView {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
obj.set_overflow(gtk::Overflow::Hidden);
self.obj().set_overflow(gtk::Overflow::Hidden);
self.setup_node_dragging();
self.setup_scroll_zooming();
self.setup_zoom_gesture();
}
fn dispose(&self, _obj: &Self::Type) {
fn dispose(&self) {
self.nodes
.borrow()
.values()
@@ -107,22 +107,19 @@ mod imp {
glib::ParamSpecOverride::for_interface::<gtk::Scrollable>("vadjustment"),
glib::ParamSpecOverride::for_interface::<gtk::Scrollable>("hscroll-policy"),
glib::ParamSpecOverride::for_interface::<gtk::Scrollable>("vscroll-policy"),
glib::ParamSpecDouble::new(
"zoom-factor",
"zoom-factor",
"zoom-factor",
0.3,
4.0,
1.0,
glib::ParamFlags::CONSTRUCT | glib::ParamFlags::READWRITE,
),
glib::ParamSpecDouble::builder("zoom-factor")
.minimum(0.3)
.maximum(4.0)
.default_value(1.0)
.flags(glib::ParamFlags::CONSTRUCT | glib::ParamFlags::READWRITE)
.build(),
]
});
PROPERTIES.as_ref()
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"hadjustment" => self.hadjustment.borrow().to_value(),
"vadjustment" => self.vadjustment.borrow().to_value(),
@@ -132,19 +129,15 @@ mod imp {
}
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let obj = self.obj();
match pspec.name() {
"hadjustment" => {
self.set_adjustment(obj, value.get().ok(), gtk::Orientation::Horizontal)
self.set_adjustment(&obj, value.get().ok(), gtk::Orientation::Horizontal)
}
"vadjustment" => {
self.set_adjustment(obj, value.get().ok(), gtk::Orientation::Vertical)
self.set_adjustment(&obj, value.get().ok(), gtk::Orientation::Vertical)
}
"hscroll-policy" | "vscroll-policy" => {}
"zoom-factor" => {
@@ -157,7 +150,9 @@ mod imp {
}
impl WidgetImpl for GraphView {
fn size_allocate(&self, widget: &Self::Type, _width: i32, _height: i32, baseline: i32) {
fn size_allocate(&self, _width: i32, _height: i32, baseline: i32) {
let widget = &*self.obj();
let zoom_factor = self.zoom_factor.get();
for (node, point) in self.nodes.borrow().values() {
@@ -165,14 +160,13 @@ mod imp {
let transform = self
.canvas_space_to_screen_space_transform()
.translate(point)
.unwrap();
.translate(point);
node.allocate(
(natural_size.width() as f64 / zoom_factor).ceil() as i32,
(natural_size.height() as f64 / zoom_factor).ceil() as i32,
baseline,
Some(&transform),
Some(transform),
);
}
@@ -184,7 +178,8 @@ mod imp {
}
}
fn snapshot(&self, widget: &Self::Type, snapshot: &gtk::Snapshot) {
fn snapshot(&self, snapshot: &gtk::Snapshot) {
let widget = &*self.obj();
let alloc = widget.allocation();
self.snapshot_background(widget, snapshot);
@@ -195,7 +190,7 @@ mod imp {
.values()
// Cull nodes from rendering when they are outside the visible canvas area
.filter(|(node, _)| alloc.intersect(&node.allocation()).is_some())
.for_each(|(node, _)| self.instance().snapshot_child(node, snapshot));
.for_each(|(node, _)| widget.snapshot_child(node, snapshot));
self.snapshot_links(widget, snapshot);
}
@@ -217,9 +212,7 @@ mod imp {
gsk::Transform::new()
.translate(&Point::new(-hadj as f32, -vadj as f32))
.unwrap()
.scale(zoom_factor as f32, zoom_factor as f32)
.unwrap()
}
/// Returns a [`gsk::Transform`] matrix that can translate from screen space to canvas space.
@@ -232,7 +225,6 @@ mod imp {
}
fn setup_node_dragging(&self) {
let obj = self.instance();
let drag_controller = gtk::GestureDrag::new();
drag_controller.connect_drag_begin(|drag_controller, x, y| {
@@ -297,12 +289,10 @@ mod imp {
),
);
});
obj.add_controller(&drag_controller);
self.obj().add_controller(drag_controller);
}
fn setup_scroll_zooming(&self) {
let obj = self.instance();
// We're only interested in the vertical axis, but for devices like touchpads,
// not capturing a small accidental horizontal move may cause the scroll to be disrupted if a widget
// higher up captures it instead.
@@ -327,7 +317,7 @@ mod imp {
gtk::Inhibit(false)
}
});
obj.add_controller(&scroll_controller);
self.obj().add_controller(scroll_controller);
}
fn setup_zoom_gesture(&self) {
@@ -355,7 +345,7 @@ mod imp {
widget.set_zoom_factor(initial_zoom * delta, gesture.bounding_box_center());
});
self.instance().add_controller(&zoom_gesture);
self.obj().add_controller(zoom_gesture);
}
fn snapshot_background(&self, widget: &super::GraphView, snapshot: &gtk::Snapshot) {
@@ -491,6 +481,7 @@ mod imp {
/// # Returns
/// `Some((from_x, from_y, to_x, to_y))` if all objects the links refers to exist as widgets.
fn get_link_coordinates(&self, link: &crate::PipewireLink) -> Option<(f64, f64, f64, f64)> {
let widget = &*self.obj();
let nodes = self.nodes.borrow();
let output_port = &nodes.get(&link.node_from)?.0.get_port(link.port_from)?;
@@ -499,7 +490,7 @@ mod imp {
(output_port.allocated_width() - output_port.width()) as f64 / 2.0;
let (from_x, from_y) = output_port.translate_coordinates(
&self.instance(),
widget,
output_port.width() as f64 + output_port_padding,
(output_port.height() / 2) as f64,
)?;
@@ -510,7 +501,7 @@ mod imp {
(input_port.allocated_width() - input_port.width()) as f64 / 2.0;
let (to_x, to_y) = input_port.translate_coordinates(
&self.instance(),
widget,
-input_port_padding,
(input_port.height() / 2) as f64,
)?;
@@ -573,7 +564,7 @@ impl GraphView {
pub const ZOOM_MAX: f64 = 4.0;
pub fn new() -> Self {
glib::Object::new(&[]).expect("Failed to create GraphView")
glib::Object::new()
}
pub fn zoom_factor(&self) -> f64 {
@@ -619,7 +610,7 @@ impl GraphView {
}
pub fn add_node(&self, id: u32, node: Node, node_type: Option<NodeType>) {
let private = imp::GraphView::from_instance(self);
let imp = self.imp();
node.set_parent(self);
// Place widgets in colums of 3, growing down
@@ -632,7 +623,7 @@ impl GraphView {
420.0
};
let y = private
let y = imp
.nodes
.borrow()
.values()
@@ -651,15 +642,11 @@ impl GraphView {
})
.map_or(20_f32, |(_x, y)| y + 100.0);
private
.nodes
.borrow_mut()
.insert(id, (node, Point::new(x, y)));
imp.nodes.borrow_mut().insert(id, (node, Point::new(x, y)));
}
pub fn remove_node(&self, id: u32) {
let private = imp::GraphView::from_instance(self);
let mut nodes = private.nodes.borrow_mut();
let mut nodes = self.imp().nodes.borrow_mut();
if let Some((node, _)) = nodes.remove(&id) {
node.unparent();
} else {
@@ -668,9 +655,7 @@ impl GraphView {
}
pub fn add_port(&self, node_id: u32, port_id: u32, port: crate::view::port::Port) {
let private = imp::GraphView::from_instance(self);
if let Some((node, _)) = private.nodes.borrow_mut().get_mut(&node_id) {
if let Some((node, _)) = self.imp().nodes.borrow_mut().get_mut(&node_id) {
node.add_port(port_id, port);
} else {
error!(
@@ -681,22 +666,22 @@ impl GraphView {
}
pub fn remove_port(&self, id: u32, node_id: u32) {
let private = imp::GraphView::from_instance(self);
let nodes = private.nodes.borrow();
let nodes = self.imp().nodes.borrow();
if let Some((node, _)) = nodes.get(&node_id) {
node.remove_port(id);
}
}
pub fn add_link(&self, link_id: u32, link: crate::PipewireLink, active: bool) {
let private = imp::GraphView::from_instance(self);
private.links.borrow_mut().insert(link_id, (link, active));
self.imp()
.links
.borrow_mut()
.insert(link_id, (link, active));
self.queue_draw();
}
pub fn set_link_state(&self, link_id: u32, active: bool) {
let private = imp::GraphView::from_instance(self);
if let Some((_, state)) = private.links.borrow_mut().get_mut(&link_id) {
if let Some((_, state)) = self.imp().links.borrow_mut().get_mut(&link_id) {
*state = active;
self.queue_draw();
} else {
@@ -705,8 +690,7 @@ impl GraphView {
}
pub fn remove_link(&self, id: u32) {
let private = imp::GraphView::from_instance(self);
let mut links = private.links.borrow_mut();
let mut links = self.imp().links.borrow_mut();
links.remove(&id);
self.queue_draw();

View File

@@ -67,31 +67,25 @@ mod imp {
}
impl ObjectImpl for Node {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
self.grid.set_parent(obj);
fn constructed(&self) {
self.parent_constructed();
self.grid.set_parent(&*self.obj());
}
fn properties() -> &'static [glib::ParamSpec] {
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
vec![
glib::ParamSpecUInt::new(
"pipewire-id",
"pipewire-id",
"pipewire-id",
u32::MIN,
u32::MAX,
0,
ParamFlags::READWRITE | ParamFlags::CONSTRUCT_ONLY,
),
glib::ParamSpecString::new("name", "name", "name", None, ParamFlags::READWRITE),
glib::ParamSpecUInt::builder("pipewire-id")
.flags(ParamFlags::READWRITE | ParamFlags::CONSTRUCT_ONLY)
.build(),
glib::ParamSpecString::builder("name").build(),
]
});
PROPERTIES.as_ref()
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"pipewire-id" => self.pipewire_id.get().to_value(),
"name" => self.label.text().to_value(),
@@ -99,13 +93,7 @@ mod imp {
}
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"name" => self.label.set_text(value.get().unwrap()),
"pipewire-id" => self.pipewire_id.set(value.get().unwrap()),
@@ -113,7 +101,7 @@ mod imp {
}
}
fn dispose(&self, _obj: &Self::Type) {
fn dispose(&self) {
self.grid.unparent();
}
}
@@ -128,8 +116,10 @@ glib::wrapper! {
impl Node {
pub fn new(name: &str, pipewire_id: u32) -> Self {
glib::Object::new(&[("name", &name), ("pipewire-id", &pipewire_id)])
.expect("Failed to create Node")
glib::Object::builder()
.property("name", &name)
.property("pipewire-id", &pipewire_id)
.build()
}
pub fn pipewire_id(&self) -> u32 {
@@ -147,37 +137,32 @@ impl Node {
}
pub fn add_port(&mut self, id: u32, port: super::port::Port) {
let private = imp::Node::from_instance(self);
let imp = self.imp();
match port.direction() {
Direction::Input => {
private
.grid
.attach(&port, 0, private.num_ports_in.get() + 1, 1, 1);
private.num_ports_in.set(private.num_ports_in.get() + 1);
imp.grid.attach(&port, 0, imp.num_ports_in.get() + 1, 1, 1);
imp.num_ports_in.set(imp.num_ports_in.get() + 1);
}
Direction::Output => {
private
.grid
.attach(&port, 1, private.num_ports_out.get() + 1, 1, 1);
private.num_ports_out.set(private.num_ports_out.get() + 1);
imp.grid.attach(&port, 1, imp.num_ports_out.get() + 1, 1, 1);
imp.num_ports_out.set(imp.num_ports_out.get() + 1);
}
}
private.ports.borrow_mut().insert(id, port);
imp.ports.borrow_mut().insert(id, port);
}
pub fn get_port(&self, id: u32) -> Option<super::port::Port> {
let private = imp::Node::from_instance(self);
private.ports.borrow_mut().get(&id).cloned()
self.imp().ports.borrow_mut().get(&id).cloned()
}
pub fn remove_port(&self, id: u32) {
let private = imp::Node::from_instance(self);
if let Some(port) = private.ports.borrow_mut().remove(&id) {
let imp = self.imp();
if let Some(port) = imp.ports.borrow_mut().remove(&id) {
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),
Direction::Input => imp.num_ports_in.set(imp.num_ports_in.get() - 1),
Direction::Output => imp.num_ports_in.set(imp.num_ports_out.get() - 1),
}
port.unparent();

View File

@@ -67,35 +67,29 @@ mod imp {
}
impl ObjectImpl for Port {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
self.label.set_parent(obj);
fn constructed(&self) {
self.parent_constructed();
self.label.set_parent(&*self.obj());
}
fn dispose(&self, _obj: &Self::Type) {
fn dispose(&self) {
self.label.unparent()
}
fn properties() -> &'static [glib::ParamSpec] {
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
vec![
glib::ParamSpecUInt::new(
"pipewire-id",
"pipewire-id",
"pipewire-id",
u32::MIN,
u32::MAX,
0,
ParamFlags::READWRITE | ParamFlags::CONSTRUCT_ONLY,
),
glib::ParamSpecString::new("name", "name", "name", None, ParamFlags::READWRITE),
glib::ParamSpecUInt::builder("pipewire-id")
.flags(ParamFlags::READWRITE | ParamFlags::CONSTRUCT_ONLY)
.build(),
glib::ParamSpecString::builder("name").build(),
]
});
PROPERTIES.as_ref()
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"pipewire-id" => self.pipewire_id.get().unwrap().to_value(),
"name" => self.label.text().to_value(),
@@ -103,13 +97,7 @@ mod imp {
}
}
fn set_property(
&self,
_obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"name" => self.label.set_text(value.get().unwrap()),
"pipewire-id" => self.pipewire_id.set(value.get().unwrap()).unwrap(),
@@ -119,14 +107,10 @@ mod imp {
fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
vec![Signal::builder(
"port-toggled",
vec![Signal::builder("port-toggled")
// Provide id of output port and input port to signal handler.
&[<u32>::static_type().into(), <u32>::static_type().into()],
// signal handler sends back nothing.
<()>::static_type().into(),
)
.build()]
.param_types([<u32>::static_type(), <u32>::static_type()])
.build()]
});
SIGNALS.as_ref()
@@ -143,13 +127,14 @@ glib::wrapper! {
impl Port {
pub fn new(id: u32, name: &str, direction: Direction, media_type: Option<MediaType>) -> Self {
// Create the widget and initialize needed fields
let res: Self = glib::Object::new(&[("pipewire-id", &id), ("name", &name)])
.expect("Failed to create Port");
let res: Self = glib::Object::builder()
.property("pipewire-id", &id)
.property("name", &name)
.build();
let private = imp::Port::from_instance(&res);
let imp = res.imp();
private
.direction
imp.direction
.set(direction)
.expect("Port direction already set");
@@ -172,7 +157,7 @@ impl Port {
trace!("Drag from port {} was cancelled", id);
false
});
res.add_controller(&drag_src);
res.add_controller(drag_src);
// The drop target will accept either a `ForwardLink` or `ReversedLink` depending in its own direction,
// and use it to emit its `port-toggled` signal.
@@ -217,7 +202,7 @@ impl Port {
);
}
}
res.add_controller(&drop_target);
res.add_controller(drop_target);
// Display a grab cursor when the mouse is over the port so the user knows it can be dragged to another port.
res.set_cursor(gtk::gdk::Cursor::from_name("grab", None).as_ref());
@@ -248,7 +233,9 @@ impl Port {
}
pub fn direction(&self) -> &Direction {
let private = imp::Port::from_instance(self);
private.direction.get().expect("Port direction is not set")
self.imp()
.direction
.get()
.expect("Port direction is not set")
}
}

View File

@@ -61,87 +61,78 @@ mod imp {
}
impl ObjectImpl for ZoomEntry {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
fn constructed(&self) {
self.parent_constructed();
self.zoom_out_button
.connect_clicked(clone!(@weak obj => move |_| {
let graphview = obj.imp().graphview.borrow();
.connect_clicked(clone!(@weak self as imp => move |_| {
let graphview = imp.graphview.borrow();
if let Some(ref graphview) = *graphview {
graphview.set_zoom_factor(graphview.zoom_factor() - 0.1, None);
}
}));
self.zoom_in_button
.connect_clicked(clone!(@weak obj => move |_| {
let graphview = obj.imp().graphview.borrow();
.connect_clicked(clone!(@weak self as imp => move |_| {
let graphview = imp.graphview.borrow();
if let Some(ref graphview) = *graphview {
graphview.set_zoom_factor(graphview.zoom_factor() + 0.1, None);
}
}));
self.entry
.connect_activate(clone!(@weak obj => move |entry| {
.connect_activate(clone!(@weak self as imp => move |entry| {
if let Ok(zoom_factor) = entry.text().trim_matches('%').parse::<f64>() {
let graphview = obj.imp().graphview.borrow();
let graphview = imp.graphview.borrow();
if let Some(ref graphview) = *graphview {
graphview.set_zoom_factor(zoom_factor / 100.0, None);
}
}
}));
self.entry
.connect_icon_press(clone!(@weak obj => move |_, pos| {
.connect_icon_press(clone!(@weak self as imp => move |_, pos| {
if pos == gtk::EntryIconPosition::Secondary {
obj.imp().popover.show();
imp.popover.show();
}
}));
self.popover.set_parent(&self.entry.get());
}
fn dispose(&self, obj: &Self::Type) {
fn dispose(&self) {
self.popover.unparent();
while let Some(child) = obj.first_child() {
while let Some(child) = self.obj().first_child() {
child.unparent();
}
}
fn properties() -> &'static [glib::ParamSpec] {
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
vec![glib::ParamSpecObject::new(
"zoomed-widget",
"zoomed widget",
"Zoomed Widget",
view::GraphView::static_type(),
glib::ParamFlags::READWRITE | glib::ParamFlags::CONSTRUCT,
)]
vec![
glib::ParamSpecObject::builder::<view::GraphView>("zoomed-widget")
.flags(glib::ParamFlags::READWRITE | glib::ParamFlags::CONSTRUCT)
.build(),
]
});
PROPERTIES.as_ref()
}
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"zoomed-widget" => self.graphview.borrow().to_value(),
_ => unimplemented!(),
}
}
fn set_property(
&self,
obj: &Self::Type,
_id: usize,
value: &glib::Value,
pspec: &glib::ParamSpec,
) {
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"zoomed-widget" => {
let widget: view::GraphView = value.get().unwrap();
widget.connect_notify_local(
Some("zoom-factor"),
clone!(@weak obj => move |graphview, _| {
let imp = obj.imp();
clone!(@weak self as imp => move |graphview, _| {
imp.update_zoom_factor_text(graphview.zoom_factor());
}),
);
@@ -174,6 +165,8 @@ glib::wrapper! {
impl ZoomEntry {
pub fn new(zoomed_widget: &view::GraphView) -> Self {
glib::Object::new(&[("zoomed-widget", zoomed_widget)]).expect("Failed to create ZoomEntry")
glib::Object::builder()
.property("zoomed-widget", zoomed_widget)
.build()
}
}