egui_node_editor/
ui_state.rs1use super::*;
2use egui::{Rect, Style, Ui, Vec2};
3use std::marker::PhantomData;
4use std::sync::Arc;
5
6use crate::scale::Scale;
7#[cfg(feature = "persistence")]
8use serde::{Deserialize, Serialize};
9
10const MIN_ZOOM: f32 = 0.2;
11const MAX_ZOOM: f32 = 2.0;
12
13#[derive(Clone)]
14#[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))]
15pub struct GraphEditorState<NodeData, DataType, ValueType, NodeTemplate, UserState> {
16 pub graph: Graph<NodeData, DataType, ValueType>,
17 pub node_order: Vec<NodeId>,
20 pub connection_in_progress: Option<(NodeId, AnyParameterId)>,
23 pub selected_nodes: Vec<NodeId>,
26 pub ongoing_box_selection: Option<egui::Pos2>,
28 pub node_positions: SecondaryMap<NodeId, egui::Pos2>,
30 pub node_finder: Option<NodeFinder<NodeTemplate>>,
32 pub pan_zoom: PanZoom,
34 pub _user_state: PhantomData<fn() -> UserState>,
35}
36
37impl<NodeData, DataType, ValueType, NodeKind, UserState>
38 GraphEditorState<NodeData, DataType, ValueType, NodeKind, UserState>
39{
40 pub fn new(default_zoom: f32) -> Self {
41 Self {
42 pan_zoom: PanZoom::new(default_zoom),
43 ..Default::default()
44 }
45 }
46}
47impl<NodeData, DataType, ValueType, NodeKind, UserState> Default
48 for GraphEditorState<NodeData, DataType, ValueType, NodeKind, UserState>
49{
50 fn default() -> Self {
51 Self {
52 graph: Default::default(),
53 node_order: Default::default(),
54 connection_in_progress: Default::default(),
55 selected_nodes: Default::default(),
56 ongoing_box_selection: Default::default(),
57 node_positions: Default::default(),
58 node_finder: Default::default(),
59 pan_zoom: Default::default(),
60 _user_state: Default::default(),
61 }
62 }
63}
64
65#[cfg(feature = "persistence")]
66fn _default_clip_rect() -> Rect {
67 Rect::NOTHING
68}
69
70#[derive(Clone)]
71#[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))]
72pub struct PanZoom {
73 pub pan: Vec2,
74 pub zoom: f32,
75 #[cfg_attr(feature = "persistence", serde(skip, default = "_default_clip_rect"))]
76 pub clip_rect: Rect,
77 #[cfg_attr(feature = "persistence", serde(skip, default))]
78 pub zoomed_style: Arc<Style>,
79 #[cfg_attr(feature = "persistence", serde(skip, default))]
80 pub started: bool,
81}
82
83impl Default for PanZoom {
84 fn default() -> Self {
85 PanZoom {
86 pan: Vec2::ZERO,
87 zoom: 1.0,
88 clip_rect: Rect::NOTHING,
89 zoomed_style: Default::default(),
90 started: false,
91 }
92 }
93}
94
95impl PanZoom {
96 pub fn new(zoom: f32) -> PanZoom {
97 let style: Style = Default::default();
98 PanZoom {
99 pan: Vec2::ZERO,
100 zoom,
101 clip_rect: Rect::NOTHING,
102 zoomed_style: Arc::new(style.scaled(1.0)),
103 started: false,
104 }
105 }
106
107 pub fn zoom(&mut self, clip_rect: Rect, style: &Arc<Style>, zoom_delta: f32) {
108 self.clip_rect = clip_rect;
109 let new_zoom = (self.zoom * zoom_delta).clamp(MIN_ZOOM, MAX_ZOOM);
110 self.zoomed_style = Arc::new(style.scaled(new_zoom));
111 self.zoom = new_zoom;
112 }
113}
114
115pub fn show_zoomed<R, F>(
116 default_style: Arc<Style>,
117 zoomed_style: Arc<Style>,
118 ui: &mut Ui,
119 add_content: F,
120) -> R
121where
122 F: FnOnce(&mut Ui) -> R,
123{
124 *ui.style_mut() = (*zoomed_style).clone();
125 let response = add_content(ui);
126 *ui.style_mut() = (*default_style).clone();
127
128 response
129}