NodeEditor

repository·main·Indexed 43 days ago

https://github.com/wieslawsoltes/nodeeditor

An Avalonia-based control for creating and editing node-based interfaces. It allows developers to render complex node graphs using customizable XAML templates and ReactiveUI-based ViewModels, featuring a modular architecture split into Model, UI, and MVVM layers.

Tokens
13.4K
Snippets
27
Records
107
Agent score
54%

What's inside NodeEditor

  1. Explore the NodeEditor API Reference

    main

    The NodeEditor API is organized into several key assemblies. To integrate or extend the editor, you should reference the appropriate assembly based on your needs:

    • NodeEditorAvalonia: The main Avalonia-based UI components.
    • NodeEditorAvalonia.Model: The data models used within the Avalonia UI layer.
    • NodeEditorAvalonia.Mvvm: MVVM (Model-View-ViewModel) patterns and components for Avalonia.
    • NodeEditorLogic.Core: The core logic engine of the node editor.
    • NodeEditorLogic.Editor: Logic specifically related to the editor's behavior and interaction.

    Use the project's navigation tree to browse specific namespaces, types, and members within these assemblies.

  2. Understand Pins (IPin and IConnectablePin)

    main

    Pins are the connection points located on nodes.

    IPin

    Basic connection points with:

    • Geometry: X, Y, Width, Height.
    • Alignment: PinAlignment (e.g., Left, Right, Top, Bottom, None).
    • Capability: CanConnect and CanDisconnect flags.

    IConnectablePin

    Extends IPin to add connection semantics:

    • Direction: PinDirection (e.g., Input, Output, or Bidirectional).
    • BusWidth: An integer representing the width for bus signals.
  3. How undo/redo snapshots work in DrawingNodeViewModel

    main

    Undo and redo functionality is implemented in DrawingNodeViewModel via the IUndoRedoHost interface using serialized snapshots.

    Key mechanics:

    • Serialization: Snapshots are captured using an INodeSerializer.
    • History Limit: The undo history is constrained by the MaxUndoEntries setting.
    • Atomicity: Commands are wrapped in undo batches to ensure changes are treated as a single unit.

    Note: If no INodeSerializer is configured, undo/redo functionality is disabled, and commands will perform direct edits without history support.

  4. Understand ConnectorViewModel and its properties

    main

    The ConnectorViewModel implements the IConnector interface and manages the visual representation of wires linking pins. It automatically observes changes to pins and parent nodes to trigger redraws during node movement or rotation.

    Key properties you can configure include:

    • Pins: The start and end pins.
    • Style: Defines the line type (Bezier, Straight, or Orthogonal).
    • Routing Mode: Determines if the path is calculated automatically or defined by you (Auto or Manual).
    • Orientation: The direction of the connector (Auto, Horizontal, or Vertical).
    • Arrow Styles: Visual markers at the ends (None, Arrow, Circle, or Diamond).
    • Waypoints: A list of points used when in Manual routing mode.
  5. Use Nudge to move nodes with arrow keys

    main

    Selected nodes can be moved using the arrow keys. The movement distance is determined by:

    • NudgeStep: The base movement increment (default is 1).
    • NudgeMultiplier: The multiplier applied when the Shift key is held (default is 10).

    Note: If snapping is enabled, the nudge operation will use the snap step instead of the base NudgeStep.

  6. How NodeEditor handles performance and hit testing

    main

    To maintain responsiveness in large graphs, NodeEditor uses spatial indexing via HitTestIndex. This index allows for fast interaction, selection, and proximity testing by organizing the graph's geometry into searchable structures.

    HitTestIndex maintains two separate R-trees:

    1. Node Bounds: An R-tree covering the bounding boxes of all nodes.
    2. Connector Segments: An R-tree covering the individual line segments that make up connector paths (including flattened Bezier curves).

    The index is updated incrementally by monitoring changes to node/connector collections, property changes on nodes and connectors (including waypoints), and routing settings changes.

  7. How connector segments are indexed for hit testing

    main
    For precise interaction with connections, NodeEditor flattens connector paths into individual line segments. This process includes Bezier flattening, ensuring that even complex curved paths are represented as a series of segments. Each segment is then indexed in an R-tree, enabling efficient intersection and proximity tests for tasks like selecting a connector or calculating routing.
  8. Understand the INodeTemplate abstraction

    main

    An INodeTemplate is the core abstraction used for drag-and-drop node creation. It defines how a node is identified in the UI and what is actually inserted into the editor. A template consists of three main parts:

    • Title: The display name shown in the toolbox.
    • Template: The actual node instance that will be inserted into the editor graph.
    • Preview: A lightweight version of the node used specifically for UI previews in the toolbox.

    NodeTemplateViewModel is provided as a default implementation of this interface.

  9. Understand the IDrawingNode abstraction

    main

    An IDrawingNode represents the root of a node graph. It extends INode and acts as the primary container for the graph's state and operations.

    Capabilities of IDrawingNode:

    • Collections: Manages Nodes, Connectors, and InkStrokes.
    • Configuration: Holds IDrawingNodeSettings.
    • Selection: Manages selection state and provides selection events.
    • Commands: Provides editor commands for clipboard operations, alignment, ordering, visibility, and more.
    • Connection Logic: Responsible for connection rejection events.
  10. How NodeEditor works: Nodes, Connectors, and ViewModels

    main

    NodeEditor is an Avalonia control designed for rendering and editing nodes and connectors.

    Key Concepts:

    • Node Contents: Defined using XAML. You can retemplate node controls, connectors, and pins using XAML or use the provided default theme.
    • Rendering: Node contents are rendered based on provided ViewModels.
    • ViewModels: The default implementation uses ReactiveUI. While you can use the provided MVVM packages, you can also create custom ViewModels by implementing the core model interfaces found in NodeEditorAvalonia.Model.
    • View Resolution: Node contents are resolved using the provided object type via a view locator.