use super::*; /// This trait must be implemented by the `ValueType` generic parameter of the /// [`Graph`]. The trait allows drawing custom inline widgets for the different /// types of the node graph. /// /// The [`Default`] trait bound is required to circumvent borrow checker issues /// using `std::mem::take` Otherwise, it would be impossible to pass the /// `node_data` parameter during `value_widget`. The default value is never /// used, so the implementation is not important, but it should be reasonably /// cheap to construct. pub trait WidgetValueTrait: Default { type Response; type UserState; type NodeData; /// This method will be called for each input parameter with a widget with /// an disconnected input only. To display UI for connected inputs use /// [`WidgetValueTrait::value_widget_connected`]. The return value is a /// vector of custom response objects which can be used to implement /// handling of side effects. If unsure, the response Vec can be empty. fn value_widget( &mut self, param_name: &str, node_id: NodeId, ui: &mut egui::Ui, user_state: &mut Self::UserState, node_data: &Self::NodeData, ) -> Vec; /// This method will be called for each input parameter with a widget with a /// connected input only. To display UI for diconnected inputs use /// [`WidgetValueTrait::value_widget`]. The return value is a vector of /// custom response objects which can be used to implement handling of /// side effects. If unsure, the response Vec can be empty. /// /// Shows the input name label by default. fn value_widget_connected( &mut self, param_name: &str, _node_id: NodeId, ui: &mut egui::Ui, _user_state: &mut Self::UserState, _node_data: &Self::NodeData, ) -> Vec { ui.label(param_name); Default::default() } } /// This trait must be implemented by the `DataType` generic parameter of the /// [`Graph`]. This trait tells the library how to visually expose data types /// to the user. pub trait DataTypeTrait: PartialEq + Eq { /// The associated port color of this datatype fn data_type_color(&self, user_state: &mut UserState) -> egui::Color32; /// The name of this datatype. Return type is specified as Cow because /// some implementations will need to allocate a new string to provide an /// answer while others won't. /// /// ## Example (borrowed value) /// Use this when you can get the name of the datatype from its fields or as /// a &'static str. Prefer this method when possible. /// ```ignore /// pub struct DataType { name: String } /// /// impl DataTypeTrait<()> for DataType { /// fn name(&self) -> std::borrow::Cow { /// Cow::Borrowed(&self.name) /// } /// } /// ``` /// /// ## Example (owned value) /// Use this when you can't derive the name of the datatype from its fields. /// ```ignore /// pub struct DataType { some_tag: i32 } /// /// impl DataTypeTrait<()> for DataType { /// fn name(&self) -> std::borrow::Cow { /// Cow::Owned(format!("Super amazing type #{}", self.some_tag)) /// } /// } /// ``` fn name(&self) -> std::borrow::Cow<'_, str>; } /// This trait must be implemented for the `NodeData` generic parameter of the /// [`Graph`]. This trait allows customizing some aspects of the node drawing. pub trait NodeDataTrait where Self: Sized, { /// Must be set to the custom user `NodeResponse` type type Response; /// Must be set to the custom user `UserState` type type UserState; /// Must be set to the custom user `DataType` type type DataType; /// Must be set to the custom user `ValueType` type type ValueType; /// Additional UI elements to draw in the nodes, after the parameters. fn bottom_ui( &self, ui: &mut egui::Ui, node_id: NodeId, graph: &Graph, user_state: &mut Self::UserState, ) -> Vec> where Self::Response: UserResponseTrait; /// UI to draw on the top bar of the node. fn top_bar_ui( &self, _ui: &mut egui::Ui, _node_id: NodeId, _graph: &Graph, _user_state: &mut Self::UserState, ) -> Vec> where Self::Response: UserResponseTrait, { Default::default() } /// UI to draw for each output /// /// Defaults to showing param_name as a simple label. fn output_ui( &self, ui: &mut egui::Ui, _node_id: NodeId, _graph: &Graph, _user_state: &mut Self::UserState, param_name: &str, ) -> Vec> where Self::Response: UserResponseTrait, { ui.label(param_name); Default::default() } /// Set background color on titlebar /// If the return value is None, the default color is set. fn titlebar_color( &self, _ui: &egui::Ui, _node_id: NodeId, _graph: &Graph, _user_state: &mut Self::UserState, ) -> Option { None } /// Separator to put between elements in the node. /// /// Invoked between inputs, outputs and bottom UI. Useful for /// complicated UIs that start to lose structure without explicit /// separators. The `param_id` argument is the id of input or output /// *preceeding* the separator. /// /// Default implementation does nothing. fn separator( &self, _ui: &mut egui::Ui, _node_id: NodeId, _param_id: AnyParameterId, _graph: &Graph, _user_state: &mut Self::UserState, ) { } fn can_delete( &self, _node_id: NodeId, _graph: &Graph, _user_state: &mut Self::UserState, ) -> bool { true } } /// This trait can be implemented by any user type. The trait tells the library /// how to enumerate the node templates it will present to the user as part of /// the node finder. pub trait NodeTemplateIter { type Item; fn all_kinds(&self) -> Vec; } /// Describes a category of nodes. /// /// Used by [`NodeTemplateTrait::node_finder_categories`] to categorize nodes /// templates into groups. /// /// If all nodes in a program are known beforehand, it's usefult to define /// an enum containing all categories and implement [`CategoryTrait`] for it. /// This will make it impossible to accidentally create a new category by /// mis-typing an existing one, like in the case of using string types. pub trait CategoryTrait { /// Name of the category. fn name(&self) -> String; } impl CategoryTrait for () { fn name(&self) -> String { String::new() } } impl CategoryTrait for &str { fn name(&self) -> String { self.to_string() } } impl CategoryTrait for String { fn name(&self) -> String { self.clone() } } /// This trait must be implemented by the `NodeTemplate` generic parameter of /// the [`GraphEditorState`]. It allows the customization of node templates. A /// node template is what describes what kinds of nodes can be added to the /// graph, what is their name, and what are their input / output parameters. pub trait NodeTemplateTrait: Clone { /// Must be set to the custom user `NodeData` type type NodeData; /// Must be set to the custom user `DataType` type type DataType; /// Must be set to the custom user `ValueType` type type ValueType; /// Must be set to the custom user `UserState` type type UserState; /// Must be a type that implements the [`CategoryTrait`] trait. /// /// `&'static str` is a good default if you intend to simply type out /// the categories of your node. Use `()` if you don't need categories /// at all. type CategoryType; /// Returns a descriptive name for the node kind, used in the node finder. /// /// The return type is Cow to allow returning owned or borrowed values /// more flexibly. Refer to the documentation for `DataTypeTrait::name` for /// more information fn node_finder_label( &self, user_state: &mut Self::UserState, ) -> std::borrow::Cow<'_, str>; /// Vec of categories to which the node belongs. /// /// It's often useful to organize similar nodes into categories, which will /// then be used by the node finder to show a more manageable UI, especially /// if the node template are numerous. fn node_finder_categories( &self, _user_state: &mut Self::UserState, ) -> Vec { Vec::default() } /// Returns a descriptive name for the node kind, used in the graph. fn node_graph_label(&self, user_state: &mut Self::UserState) -> String; /// Returns the user data for this node kind. fn user_data(&self, user_state: &mut Self::UserState) -> Self::NodeData; /// This function is run when this node kind gets added to the graph. The /// node will be empty by default, and this function can be used to fill its /// parameters. fn build_node( &self, graph: &mut Graph, user_state: &mut Self::UserState, node_id: NodeId, ); } /// The custom user response types when drawing nodes in the graph must /// implement this trait. pub trait UserResponseTrait: Clone + std::fmt::Debug {}