mirror of
https://gitlab.freedesktop.org/pipewire/helvum
synced 2026-03-15 03:26:10 +08:00
graph: Move port link anchor calculation into port widget
This commit is contained in:
@@ -432,77 +432,69 @@ mod imp {
|
||||
|
||||
for link in self.links.borrow().iter() {
|
||||
// TODO: Do not draw links when they are outside the view
|
||||
if let Some((from_x, from_y, to_x, to_y)) = self.get_link_coordinates(link) {
|
||||
link_cr.move_to(from_x, from_y);
|
||||
|
||||
// Use dashed line for inactive links, full line otherwise.
|
||||
if link.active() {
|
||||
link_cr.set_dash(&[], 0.0);
|
||||
} else {
|
||||
link_cr.set_dash(&[10.0, 5.0], 0.0);
|
||||
}
|
||||
|
||||
// If the output port is farther right than the input port and they have
|
||||
// a similar y coordinate, apply a y offset to the control points
|
||||
// so that the curve sticks out a bit.
|
||||
let y_control_offset = if from_x > to_x {
|
||||
f64::max(0.0, 25.0 - (from_y - to_y).abs())
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
// Place curve control offset by half the x distance between the two points.
|
||||
// This makes the curve scale well for varying distances between the two ports,
|
||||
// especially when the output port is farther right than the input port.
|
||||
let half_x_dist = f64::abs(from_x - to_x) / 2.0;
|
||||
link_cr.curve_to(
|
||||
from_x + half_x_dist,
|
||||
from_y - y_control_offset,
|
||||
to_x - half_x_dist,
|
||||
to_y - y_control_offset,
|
||||
to_x,
|
||||
to_y,
|
||||
);
|
||||
|
||||
if let Err(e) = link_cr.stroke() {
|
||||
warn!("Failed to draw graphview links: {}", e);
|
||||
};
|
||||
} else {
|
||||
let Some((output_anchor, input_anchor)) = self.get_link_coordinates(link) else {
|
||||
warn!("Could not get allocation of ports of link: {:?}", link);
|
||||
continue;
|
||||
};
|
||||
|
||||
let output_x: f64 = output_anchor.x().into();
|
||||
let output_y: f64 = output_anchor.y().into();
|
||||
let input_x: f64 = input_anchor.x().into();
|
||||
let input_y: f64 = input_anchor.y().into();
|
||||
|
||||
// Use dashed line for inactive links, full line otherwise.
|
||||
if link.active() {
|
||||
link_cr.set_dash(&[], 0.0);
|
||||
} else {
|
||||
link_cr.set_dash(&[10.0, 5.0], 0.0);
|
||||
}
|
||||
|
||||
// If the output port is farther right than the input port and they have
|
||||
// a similar y coordinate, apply a y offset to the control points
|
||||
// so that the curve sticks out a bit.
|
||||
let y_control_offset = if output_x > input_x {
|
||||
f64::max(0.0, 25.0 - (output_y - input_y).abs())
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
// Place curve control offset by half the x distance between the two points.
|
||||
// This makes the curve scale well for varying distances between the two ports,
|
||||
// especially when the output port is farther right than the input port.
|
||||
let half_x_dist = f64::abs(output_x - input_x) / 2.0;
|
||||
link_cr.move_to(output_x, output_y);
|
||||
link_cr.curve_to(
|
||||
output_x + half_x_dist,
|
||||
output_y - y_control_offset,
|
||||
input_x - half_x_dist,
|
||||
input_y - y_control_offset,
|
||||
input_x,
|
||||
input_y,
|
||||
);
|
||||
|
||||
if let Err(e) = link_cr.stroke() {
|
||||
warn!("Failed to draw graphview links: {}", e);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Get coordinates for the drawn link to start at and to end at.
|
||||
///
|
||||
/// # 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: &Link) -> Option<(f64, f64, f64, f64)> {
|
||||
/// `Some((output_anchor, input_anchor))` if all objects the links refers to exist as widgets
|
||||
/// and those widgets are contained by the graph.
|
||||
///
|
||||
/// The returned coordinates are in screen-space of the graph.
|
||||
fn get_link_coordinates(&self, link: &Link) -> Option<(graphene::Point, graphene::Point)> {
|
||||
let widget = &*self.obj();
|
||||
|
||||
let output_port = link.output_port()?;
|
||||
|
||||
let output_port_padding =
|
||||
(output_port.allocated_width() - output_port.width()) as f64 / 2.0;
|
||||
|
||||
let (from_x, from_y) = output_port.translate_coordinates(
|
||||
widget,
|
||||
output_port.width() as f64 + output_port_padding,
|
||||
(output_port.height() / 2) as f64,
|
||||
)?;
|
||||
let output_anchor = output_port.compute_point(widget, &output_port.link_anchor())?;
|
||||
|
||||
let input_port = link.input_port()?;
|
||||
let input_anchor = input_port.compute_point(widget, &input_port.link_anchor())?;
|
||||
|
||||
let input_port_padding =
|
||||
(input_port.allocated_width() - input_port.width()) as f64 / 2.0;
|
||||
|
||||
let (to_x, to_y) = input_port.translate_coordinates(
|
||||
widget,
|
||||
-input_port_padding,
|
||||
(input_port.height() / 2) as f64,
|
||||
)?;
|
||||
|
||||
Some((from_x, from_y, to_x, to_y))
|
||||
Some((output_anchor, input_anchor))
|
||||
}
|
||||
|
||||
fn set_adjustment(
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
use gtk::{
|
||||
gdk,
|
||||
glib::{self, clone, subclass::Signal},
|
||||
graphene,
|
||||
prelude::*,
|
||||
subclass::prelude::*,
|
||||
};
|
||||
@@ -223,4 +224,20 @@ impl Port {
|
||||
.get()
|
||||
.expect("Port direction is not set")
|
||||
}
|
||||
|
||||
pub fn link_anchor(&self) -> graphene::Point {
|
||||
let style_context = self.style_context();
|
||||
let padding_right: f32 = style_context.padding().right().into();
|
||||
let border_right: f32 = style_context.border().right().into();
|
||||
let padding_left: f32 = style_context.padding().left().into();
|
||||
let border_left: f32 = style_context.border().left().into();
|
||||
|
||||
graphene::Point::new(
|
||||
match self.direction() {
|
||||
Direction::Output => self.width() as f32 + padding_right + border_right,
|
||||
Direction::Input => 0.0 - padding_left - border_left,
|
||||
},
|
||||
self.height() as f32 / 2.0,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user