egui_graph_edit/traits.rs
1use super::*;
2
3/// This trait must be implemented by the `ValueType` generic parameter of the
4/// [`Graph`]. The trait allows drawing custom inline widgets for the different
5/// types of the node graph.
6///
7/// The [`Default`] trait bound is required to circumvent borrow checker issues
8/// using `std::mem::take` Otherwise, it would be impossible to pass the
9/// `node_data` parameter during `value_widget`. The default value is never
10/// used, so the implementation is not important, but it should be reasonably
11/// cheap to construct.
12pub trait WidgetValueTrait: Default {
13 type Response;
14 type UserState;
15 type NodeData;
16
17 /// This method will be called for each input parameter with a widget with an disconnected
18 /// input only. To display UI for connected inputs use [`WidgetValueTrait::value_widget_connected`].
19 /// The return value is a vector of custom response objects which can be used
20 /// to implement handling of side effects. If unsure, the response Vec can
21 /// be empty.
22 fn value_widget(
23 &mut self,
24 param_name: &str,
25 node_id: NodeId,
26 ui: &mut egui::Ui,
27 user_state: &mut Self::UserState,
28 node_data: &Self::NodeData,
29 ) -> Vec<Self::Response>;
30
31 /// This method will be called for each input parameter with a widget with a connected
32 /// input only. To display UI for diconnected inputs use [`WidgetValueTrait::value_widget`].
33 /// The return value is a vector of custom response objects which can be used
34 /// to implement handling of side effects. If unsure, the response Vec can
35 /// be empty.
36 ///
37 /// Shows the input name label by default.
38 fn value_widget_connected(
39 &mut self,
40 param_name: &str,
41 _node_id: NodeId,
42 ui: &mut egui::Ui,
43 _user_state: &mut Self::UserState,
44 _node_data: &Self::NodeData,
45 ) -> Vec<Self::Response> {
46 ui.label(param_name);
47
48 Default::default()
49 }
50}
51
52/// This trait must be implemented by the `DataType` generic parameter of the
53/// [`Graph`]. This trait tells the library how to visually expose data types
54/// to the user.
55pub trait DataTypeTrait<UserState>: PartialEq + Eq {
56 /// The associated port color of this datatype
57 fn data_type_color(&self, user_state: &mut UserState) -> egui::Color32;
58
59 /// The name of this datatype. Return type is specified as Cow<str> because
60 /// some implementations will need to allocate a new string to provide an
61 /// answer while others won't.
62 ///
63 /// ## Example (borrowed value)
64 /// Use this when you can get the name of the datatype from its fields or as
65 /// a &'static str. Prefer this method when possible.
66 /// ```ignore
67 /// pub struct DataType { name: String }
68 ///
69 /// impl DataTypeTrait<()> for DataType {
70 /// fn name(&self) -> std::borrow::Cow<str> {
71 /// Cow::Borrowed(&self.name)
72 /// }
73 /// }
74 /// ```
75 ///
76 /// ## Example (owned value)
77 /// Use this when you can't derive the name of the datatype from its fields.
78 /// ```ignore
79 /// pub struct DataType { some_tag: i32 }
80 ///
81 /// impl DataTypeTrait<()> for DataType {
82 /// fn name(&self) -> std::borrow::Cow<str> {
83 /// Cow::Owned(format!("Super amazing type #{}", self.some_tag))
84 /// }
85 /// }
86 /// ```
87 fn name(&self) -> std::borrow::Cow<str>;
88}
89
90/// This trait must be implemented for the `NodeData` generic parameter of the
91/// [`Graph`]. This trait allows customizing some aspects of the node drawing.
92pub trait NodeDataTrait
93where
94 Self: Sized,
95{
96 /// Must be set to the custom user `NodeResponse` type
97 type Response;
98 /// Must be set to the custom user `UserState` type
99 type UserState;
100 /// Must be set to the custom user `DataType` type
101 type DataType;
102 /// Must be set to the custom user `ValueType` type
103 type ValueType;
104
105 /// Additional UI elements to draw in the nodes, after the parameters.
106 fn bottom_ui(
107 &self,
108 ui: &mut egui::Ui,
109 node_id: NodeId,
110 graph: &Graph<Self, Self::DataType, Self::ValueType>,
111 user_state: &mut Self::UserState,
112 ) -> Vec<NodeResponse<Self::Response, Self>>
113 where
114 Self::Response: UserResponseTrait;
115
116 /// UI to draw on the top bar of the node.
117 fn top_bar_ui(
118 &self,
119 _ui: &mut egui::Ui,
120 _node_id: NodeId,
121 _graph: &Graph<Self, Self::DataType, Self::ValueType>,
122 _user_state: &mut Self::UserState,
123 ) -> Vec<NodeResponse<Self::Response, Self>>
124 where
125 Self::Response: UserResponseTrait,
126 {
127 Default::default()
128 }
129
130 /// UI to draw for each output
131 ///
132 /// Defaults to showing param_name as a simple label.
133 fn output_ui(
134 &self,
135 ui: &mut egui::Ui,
136 _node_id: NodeId,
137 _graph: &Graph<Self, Self::DataType, Self::ValueType>,
138 _user_state: &mut Self::UserState,
139 param_name: &str,
140 ) -> Vec<NodeResponse<Self::Response, Self>>
141 where
142 Self::Response: UserResponseTrait,
143 {
144 ui.label(param_name);
145
146 Default::default()
147 }
148
149 /// Set background color on titlebar
150 /// If the return value is None, the default color is set.
151 fn titlebar_color(
152 &self,
153 _ui: &egui::Ui,
154 _node_id: NodeId,
155 _graph: &Graph<Self, Self::DataType, Self::ValueType>,
156 _user_state: &mut Self::UserState,
157 ) -> Option<egui::Color32> {
158 None
159 }
160
161 /// Separator to put between elements in the node.
162 ///
163 /// Invoked between inputs, outputs and bottom UI. Useful for
164 /// complicated UIs that start to lose structure without explicit
165 /// separators. The `param_id` argument is the id of input or output
166 /// *preceeding* the separator.
167 ///
168 /// Default implementation does nothing.
169 fn separator(
170 &self,
171 _ui: &mut egui::Ui,
172 _node_id: NodeId,
173 _param_id: AnyParameterId,
174 _graph: &Graph<Self, Self::DataType, Self::ValueType>,
175 _user_state: &mut Self::UserState,
176 ) {
177 }
178
179 fn can_delete(
180 &self,
181 _node_id: NodeId,
182 _graph: &Graph<Self, Self::DataType, Self::ValueType>,
183 _user_state: &mut Self::UserState,
184 ) -> bool {
185 true
186 }
187
188 fn can_flip(
189 &self,
190 _node_id: NodeId,
191 _graph: &Graph<Self, Self::DataType, Self::ValueType>,
192 _user_state: &mut Self::UserState,
193 ) -> bool {
194 true
195 }
196}
197
198/// This trait can be implemented by any user type. The trait tells the library
199/// how to enumerate the node templates it will present to the user as part of
200/// the node finder.
201pub trait NodeTemplateIter {
202 type Item;
203 fn all_kinds(&self) -> Vec<Self::Item>;
204}
205
206/// Describes a category of nodes.
207///
208/// Used by [`NodeTemplateTrait::node_finder_categories`] to categorize nodes
209/// templates into groups.
210///
211/// If all nodes in a program are known beforehand, it's usefult to define
212/// an enum containing all categories and implement [`CategoryTrait`] for it. This will
213/// make it impossible to accidentally create a new category by mis-typing an existing
214/// one, like in the case of using string types.
215pub trait CategoryTrait {
216 /// Name of the category.
217 fn name(&self) -> String;
218}
219
220impl CategoryTrait for () {
221 fn name(&self) -> String {
222 String::new()
223 }
224}
225
226impl CategoryTrait for &str {
227 fn name(&self) -> String {
228 self.to_string()
229 }
230}
231
232impl CategoryTrait for String {
233 fn name(&self) -> String {
234 self.clone()
235 }
236}
237
238/// This trait must be implemented by the `NodeTemplate` generic parameter of
239/// the [`GraphEditorState`]. It allows the customization of node templates. A
240/// node template is what describes what kinds of nodes can be added to the
241/// graph, what is their name, and what are their input / output parameters.
242pub trait NodeTemplateTrait: Clone {
243 /// Must be set to the custom user `NodeData` type
244 type NodeData;
245 /// Must be set to the custom user `DataType` type
246 type DataType;
247 /// Must be set to the custom user `ValueType` type
248 type ValueType;
249 /// Must be set to the custom user `UserState` type
250 type UserState;
251 /// Must be a type that implements the [`CategoryTrait`] trait.
252 ///
253 /// `&'static str` is a good default if you intend to simply type out
254 /// the categories of your node. Use `()` if you don't need categories
255 /// at all.
256 type CategoryType;
257
258 /// Returns a descriptive name for the node kind, used in the node finder.
259 ///
260 /// The return type is Cow<str> to allow returning owned or borrowed values
261 /// more flexibly. Refer to the documentation for `DataTypeTrait::name` for
262 /// more information
263 fn node_finder_label(&self, user_state: &mut Self::UserState) -> std::borrow::Cow<str>;
264
265 /// Vec of categories to which the node belongs.
266 ///
267 /// It's often useful to organize similar nodes into categories, which will
268 /// then be used by the node finder to show a more manageable UI, especially
269 /// if the node template are numerous.
270 fn node_finder_categories(&self, _user_state: &mut Self::UserState) -> Vec<Self::CategoryType> {
271 Vec::default()
272 }
273
274 /// Returns a descriptive name for the node kind, used in the graph.
275 fn node_graph_label(&self, user_state: &mut Self::UserState) -> String;
276
277 /// Returns the user data for this node kind.
278 fn user_data(&self, user_state: &mut Self::UserState) -> Self::NodeData;
279
280 /// This function is run when this node kind gets added to the graph. The
281 /// node will be empty by default, and this function can be used to fill its
282 /// parameters.
283 fn build_node(
284 &self,
285 graph: &mut Graph<Self::NodeData, Self::DataType, Self::ValueType>,
286 user_state: &mut Self::UserState,
287 node_id: NodeId,
288 );
289}
290
291/// The custom user response types when drawing nodes in the graph must
292/// implement this trait.
293pub trait UserResponseTrait: Clone + std::fmt::Debug {}