Skip to main content

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    /// Set an outer border color for the node.
162    /// If the return value is None, no custom border is drawn.
163    fn border_color(
164        &self,
165        _ui: &egui::Ui,
166        _node_id: NodeId,
167        _graph: &Graph<Self, Self::DataType, Self::ValueType>,
168        _user_state: &mut Self::UserState,
169    ) -> Option<egui::Color32> {
170        None
171    }
172
173    /// Set the width of a custom outer border.
174    /// This is only used when `border_color` returns `Some`.
175    fn border_width(
176        &self,
177        _ui: &egui::Ui,
178        _node_id: NodeId,
179        _graph: &Graph<Self, Self::DataType, Self::ValueType>,
180        _user_state: &mut Self::UserState,
181    ) -> f32 {
182        2.0
183    }
184
185    /// Separator to put between elements in the node.
186    ///
187    /// Invoked between inputs, outputs and bottom UI. Useful for
188    /// complicated UIs that start to lose structure without explicit
189    /// separators. The `param_id` argument is the id of input or output
190    /// *preceeding* the separator.
191    ///
192    /// Default implementation does nothing.
193    fn separator(
194        &self,
195        _ui: &mut egui::Ui,
196        _node_id: NodeId,
197        _param_id: AnyParameterId,
198        _graph: &Graph<Self, Self::DataType, Self::ValueType>,
199        _user_state: &mut Self::UserState,
200    ) {
201    }
202
203    fn can_delete(
204        &self,
205        _node_id: NodeId,
206        _graph: &Graph<Self, Self::DataType, Self::ValueType>,
207        _user_state: &mut Self::UserState,
208    ) -> bool {
209        true
210    }
211
212    fn can_flip(
213        &self,
214        _node_id: NodeId,
215        _graph: &Graph<Self, Self::DataType, Self::ValueType>,
216        _user_state: &mut Self::UserState,
217    ) -> bool {
218        true
219    }
220}
221
222/// This trait can be implemented by any user type. The trait tells the library
223/// how to enumerate the node templates it will present to the user as part of
224/// the node finder.
225pub trait NodeTemplateIter {
226    type Item;
227    fn all_kinds(&self) -> Vec<Self::Item>;
228}
229
230/// Describes a category of nodes.
231///
232/// Used by [`NodeTemplateTrait::node_finder_categories`] to categorize nodes
233/// templates into groups.
234///
235/// If all nodes in a program are known beforehand, it's usefult to define
236/// an enum containing all categories and implement [`CategoryTrait`] for it. This will
237/// make it impossible to accidentally create a new category by mis-typing an existing
238/// one, like in the case of using string types.
239pub trait CategoryTrait {
240    /// Name of the category.
241    fn name(&self) -> String;
242}
243
244impl CategoryTrait for () {
245    fn name(&self) -> String {
246        String::new()
247    }
248}
249
250impl CategoryTrait for &str {
251    fn name(&self) -> String {
252        self.to_string()
253    }
254}
255
256impl CategoryTrait for String {
257    fn name(&self) -> String {
258        self.clone()
259    }
260}
261
262/// This trait must be implemented by the `NodeTemplate` generic parameter of
263/// the [`GraphEditorState`]. It allows the customization of node templates. A
264/// node template is what describes what kinds of nodes can be added to the
265/// graph, what is their name, and what are their input / output parameters.
266pub trait NodeTemplateTrait: Clone {
267    /// Must be set to the custom user `NodeData` type
268    type NodeData;
269    /// Must be set to the custom user `DataType` type
270    type DataType;
271    /// Must be set to the custom user `ValueType` type
272    type ValueType;
273    /// Must be set to the custom user `UserState` type
274    type UserState;
275    /// Must be a type that implements the [`CategoryTrait`] trait.
276    ///
277    /// `&'static str` is a good default if you intend to simply type out
278    /// the categories of your node. Use `()` if you don't need categories
279    /// at all.
280    type CategoryType;
281
282    /// Returns a descriptive name for the node kind, used in the node finder.
283    ///
284    /// The return type is Cow<str> to allow returning owned or borrowed values
285    /// more flexibly. Refer to the documentation for `DataTypeTrait::name` for
286    /// more information
287    fn node_finder_label(&self, user_state: &mut Self::UserState) -> std::borrow::Cow<'_, str>;
288
289    /// Vec of categories to which the node belongs.
290    ///
291    /// It's often useful to organize similar nodes into categories, which will
292    /// then be used by the node finder to show a more manageable UI, especially
293    /// if the node template are numerous.
294    fn node_finder_categories(&self, _user_state: &mut Self::UserState) -> Vec<Self::CategoryType> {
295        Vec::default()
296    }
297
298    /// Returns a descriptive name for the node kind, used in the graph.
299    fn node_graph_label(&self, user_state: &mut Self::UserState) -> String;
300
301    /// Returns the user data for this node kind.
302    fn user_data(&self, user_state: &mut Self::UserState) -> Self::NodeData;
303
304    /// This function is run when this node kind gets added to the graph. The
305    /// node will be empty by default, and this function can be used to fill its
306    /// parameters.
307    fn build_node(
308        &self,
309        graph: &mut Graph<Self::NodeData, Self::DataType, Self::ValueType>,
310        user_state: &mut Self::UserState,
311        node_id: NodeId,
312    );
313}
314
315/// The custom user response types when drawing nodes in the graph must
316/// implement this trait.
317pub trait UserResponseTrait: Clone + std::fmt::Debug {}