ferrum_flow/plugins/
fit_all.rs1use gpui::{Bounds, Point, px};
2
3use crate::{
4 Graph,
5 plugin::{FlowEvent, InitPluginContext, Plugin, PluginContext, primary_platform_modifier},
6 plugins::viewport_frame::{apply_frame_world_rect_direct, frame_world_rect},
7};
8
9pub struct FitAllGraphPlugin;
14
15impl FitAllGraphPlugin {
16 pub fn new() -> Self {
17 Self
18 }
19}
20
21fn graph_world_bounds_graph(graph: &Graph) -> Option<(f32, f32, f32, f32)> {
22 let mut min_x = f32::MAX;
23 let mut min_y = f32::MAX;
24 let mut max_x = f32::MIN;
25 let mut max_y = f32::MIN;
26 let mut any = false;
27
28 for n in graph.nodes().values() {
29 let x: f32 = n.x.into();
30 let y: f32 = n.y.into();
31 let w: f32 = n.size.width.into();
32 let h: f32 = n.size.height.into();
33 min_x = min_x.min(x);
34 min_y = min_y.min(y);
35 max_x = max_x.max(x + w);
36 max_y = max_y.max(y + h);
37 any = true;
38 }
39
40 if !any {
41 return None;
42 }
43
44 Some((
45 min_x,
46 min_y,
47 (max_x - min_x).max(1.0),
48 (max_y - min_y).max(1.0),
49 ))
50}
51
52fn graph_world_bounds(ctx: &PluginContext) -> Option<(f32, f32, f32, f32)> {
53 graph_world_bounds_graph(ctx.graph)
54}
55
56fn fit_all(ctx: &mut PluginContext) {
57 let Some((bx, by, bw, bh)) = graph_world_bounds(ctx) else {
58 return;
59 };
60 frame_world_rect(ctx, bx, by, bw, bh);
61}
62
63pub(crate) fn fit_entire_graph(ctx: &mut PluginContext) {
64 fit_all(ctx);
65}
66
67impl Plugin for FitAllGraphPlugin {
68 fn name(&self) -> &'static str {
69 "fit_all_graph"
70 }
71
72 fn setup(&mut self, ctx: &mut InitPluginContext) {
73 let Some((bx, by, bw, bh)) = graph_world_bounds_graph(ctx.graph) else {
74 return;
75 };
76 let win_w: f32 = ctx.drawable_size.width.into();
77 let win_h: f32 = ctx.drawable_size.height.into();
78 apply_frame_world_rect_direct(ctx.viewport, win_w, win_h, bx, by, bw, bh);
79 ctx.viewport.window_bounds = Some(Bounds::new(
80 Point::new(px(0.0), px(0.0)),
81 ctx.drawable_size,
82 ));
83 }
84
85 fn priority(&self) -> i32 {
86 88
87 }
88
89 fn on_event(
90 &mut self,
91 event: &FlowEvent,
92 ctx: &mut PluginContext,
93 ) -> crate::plugin::EventResult {
94 if let FlowEvent::Input(crate::plugin::InputEvent::KeyDown(ev)) = event {
95 if primary_platform_modifier(ev)
96 && !ev.keystroke.modifiers.shift
97 && ev.keystroke.key == "0"
98 {
99 fit_all(ctx);
100 return crate::plugin::EventResult::Stop;
101 }
102 }
103 crate::plugin::EventResult::Continue
104 }
105}