#![deny(missing_docs)]
#![warn(rustdoc::broken_intra_doc_links)]
use imnodes_sys as sys;
#[cfg(feature = "include_low_level_bindings")]
pub mod internal {
pub use imnodes_sys::*;
}
mod context;
pub use context::*;
mod helpers;
mod styling;
pub use styling::*;
mod scopes;
pub use scopes::*;
pub use sys::{ImNodesIO, ImVec2};
#[derive(Debug)]
pub struct IdentifierGenerator {
current_node: i32,
current_attribute: i32,
current_link: i32,
}
impl IdentifierGenerator {
pub(crate) fn new() -> Self {
Self {
current_node: 0,
current_attribute: 0,
current_link: 0,
}
}
pub fn next_node(&mut self) -> NodeId {
let id = self.current_node;
self.current_node = self.current_node.checked_add(1).unwrap();
NodeId { id }
}
pub fn next_input_pin(&mut self) -> InputPinId {
let id = self.current_attribute;
self.current_attribute = self.current_attribute.checked_add(1).unwrap();
InputPinId { id }
}
pub fn next_output_pin(&mut self) -> OutputPinId {
let id = self.current_attribute;
self.current_attribute = self.current_attribute.checked_add(1).unwrap();
OutputPinId { id }
}
pub fn next_attribute(&mut self) -> AttributeId {
let id = self.current_attribute;
self.current_attribute = self.current_attribute.checked_add(1).unwrap();
AttributeId { id }
}
pub fn next_link(&mut self) -> LinkId {
let id = self.current_link;
self.current_link = self.current_link.checked_add(1).unwrap();
LinkId { id }
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub struct AttributeId {
id: i32,
}
impl From<AttributeId> for i32 {
fn from(val: AttributeId) -> Self {
val.id
}
}
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
pub enum CoordinateSystem {
ScreenSpace,
EditorSpace,
GridSpace,
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub struct NodeId {
id: i32,
}
impl NodeId {
#[doc(alias = "SetNodeDraggable")]
#[must_use]
pub fn set_draggable(&self, draggable: bool) -> &Self {
unsafe { sys::imnodes_SetNodeDraggable(self.id, draggable) };
self
}
#[doc(alias = "EditorContextMoveToNode")]
#[must_use]
pub fn move_editor_to(&self) -> &Self {
unsafe {
sys::imnodes_EditorContextMoveToNode(self.id);
}
self
}
#[doc(alias = "GetNodeDimensions")]
#[must_use]
pub fn get_dimensions(&self) -> ImVec2 {
let mut dimension = ImVec2 { x: 0.0, y: 0.0 };
unsafe {
sys::imnodes_GetNodeDimensions(core::ptr::from_mut(&mut dimension), self.id);
}
dimension
}
#[doc(
alias = "SetNodeScreenSpacePos",
alias = "SetNodeEditorSpacePos",
alias = "SetNodeGridSpacePos"
)]
#[must_use]
pub fn set_position(&self, x: f32, y: f32, coordinate_system: CoordinateSystem) -> &Self {
let pos = ImVec2 { x, y };
match coordinate_system {
CoordinateSystem::ScreenSpace => unsafe {
sys::imnodes_SetNodeScreenSpacePos(self.id, pos);
},
CoordinateSystem::EditorSpace => unsafe {
sys::imnodes_SetNodeEditorSpacePos(self.id, pos);
},
CoordinateSystem::GridSpace => unsafe {
sys::imnodes_SetNodeGridSpacePos(self.id, pos);
},
};
self
}
#[doc(
alias = "GetNodeScreenSpacePos",
alias = "GetNodeEditorSpacePos",
alias = "GetNodeGridSpacePos"
)]
#[must_use]
pub fn get_position(&self, coordinate_system: CoordinateSystem) -> ImVec2 {
let mut pos = ImVec2 { x: 0.0, y: 0.0 };
match coordinate_system {
CoordinateSystem::ScreenSpace => unsafe {
sys::imnodes_GetNodeScreenSpacePos(core::ptr::from_mut(&mut pos), self.id);
},
CoordinateSystem::EditorSpace => unsafe {
sys::imnodes_GetNodeEditorSpacePos(core::ptr::from_mut(&mut pos), self.id);
},
CoordinateSystem::GridSpace => unsafe {
sys::imnodes_GetNodeGridSpacePos(core::ptr::from_mut(&mut pos), self.id);
},
};
pos
}
#[doc(alias = "SnapNodeToGrid")]
#[must_use]
pub fn snap_to_grid(&self) -> &Self {
unsafe { sys::imnodes_SnapNodeToGrid(self.id) };
self
}
#[doc(alias = "SelectNode")]
#[must_use]
pub fn select(&self) -> &Self {
unsafe { sys::imnodes_SelectNode(self.id) };
self
}
#[doc(alias = "ClearNodeSelection_Int")]
#[must_use]
pub fn deselect(&self) -> &Self {
unsafe { sys::imnodes_ClearNodeSelection_Int(self.id) };
self
}
#[doc(alias = "IsNodeSelected")]
#[must_use]
pub fn is_selected(&self) -> bool {
unsafe { sys::imnodes_IsNodeSelected(self.id) }
}
}
impl From<NodeId> for i32 {
fn from(val: NodeId) -> Self {
val.id
}
}
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub struct PinId {
id: i32,
}
impl PinId {
#[doc(alias = "IsLinkStarted")]
#[must_use]
pub fn is_start_of_link(&self, scope: &OuterScope) -> bool {
Some(*self) == scope.from_where_link_started()
}
#[doc(alias = "IsLinkDropped")]
#[must_use]
pub fn dropped_link(&self, including_detached_links: bool, scope: &OuterScope) -> bool {
Some(*self) == scope.from_where_link_dropped(including_detached_links)
}
}
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub struct InputPinId {
id: i32,
}
impl From<InputPinId> for i32 {
fn from(val: InputPinId) -> Self {
val.id
}
}
impl From<InputPinId> for PinId {
fn from(val: InputPinId) -> Self {
Self { id: val.id }
}
}
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub struct OutputPinId {
id: i32,
}
impl From<OutputPinId> for i32 {
fn from(val: OutputPinId) -> Self {
val.id
}
}
impl From<OutputPinId> for PinId {
fn from(val: OutputPinId) -> Self {
Self { id: val.id }
}
}
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub struct LinkId {
id: i32,
}
impl LinkId {
#[doc(alias = "IsLinkDestroyed")]
#[must_use]
pub fn is_destroyed(&self, scope: &OuterScope) -> bool {
Some(*self) == scope.get_destroyed_link()
}
#[doc(alias = "SelectLink")]
#[must_use]
pub fn select(&self) -> &Self {
unsafe { sys::imnodes_SelectLink(self.id) };
self
}
#[doc(alias = "ClearLinkSelection_Int")]
#[must_use]
pub fn deselect(&self) -> &Self {
unsafe { sys::imnodes_ClearLinkSelection_Int(self.id) };
self
}
#[doc(alias = "IsLinkSelected")]
#[must_use]
pub fn is_selected(&self) -> bool {
unsafe { sys::imnodes_IsLinkSelected(self.id) }
}
}
impl From<LinkId> for i32 {
fn from(val: LinkId) -> Self {
val.id
}
}
pub trait Hoverable {
#[doc(
alias = "IsPinHovered",
alias = "IsNodeHovered",
alias = "IsLinkHovered"
)]
fn is_hovered(&self, scope: &OuterScope) -> bool;
}
impl Hoverable for OutputPinId {
#[doc(alias = "IsPinHovered")]
fn is_hovered(&self, scope: &OuterScope) -> bool {
Some(PinId { id: self.id }) == scope.get_hovered_pin()
}
}
impl Hoverable for InputPinId {
#[doc(alias = "IsPinHovered")]
fn is_hovered(&self, scope: &OuterScope) -> bool {
Some(PinId { id: self.id }) == scope.get_hovered_pin()
}
}
impl Hoverable for NodeId {
#[doc(alias = "IsNodeHovered")]
fn is_hovered(&self, _scope: &OuterScope) -> bool {
Some(*self) == get_hovered_node()
}
}
impl Hoverable for LinkId {
#[doc(alias = "IsLinkHovered")]
fn is_hovered(&self, scope: &OuterScope) -> bool {
Some(*self) == scope.get_hovered_link()
}
}
#[doc(alias = "IsNodeHovered")]
#[must_use]
pub fn get_hovered_node() -> Option<NodeId> {
let mut id: i32 = -1;
let ok = unsafe { sys::imnodes_IsNodeHovered(core::ptr::from_mut(&mut id)) };
if ok && id >= 0 {
Some(NodeId { id })
} else {
None
}
}
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub struct Link {
pub start_node: NodeId,
pub end_node: NodeId,
pub start_pin: OutputPinId,
pub end_pin: InputPinId,
pub created_from_snap: bool,
}