The nodes and edges of a canvas.
graph =
Hakushi.Graph.new(
nodes: [
%{id: "users", type: "table", x: 0, y: 0, data: %{name: "users"}},
%{id: "orders", type: "table", x: 320, y: 40, data: %{name: "orders"}}
],
edges: [%{source: "orders", source_handle: "user_id", target: "users", target_handle: "id"}]
)A graph keeps the order of its nodes, which is the order in which they are drawn: a node drawn later is over the ones before it. New nodes go last.
apply/2 applies a Hakushi.Change and gives back the change that
undoes it; the canvas uses it for every change, and so can the app, to
keep its own copy of the graph or to save it.
Summary
Functions
Applies a change. Gives back the graph, the change as it applied, and the change that undoes it
The box around the nodes, {x, y, width, height}, or nil for a graph
without nodes. A node without a size counts as a point.
The ids of the nodes in a node (its children), in the order they are drawn.
The ids of the nodes in a node, and in those, all the way down, in the order they are drawn.
What changed from one graph to another: the nodes and edges that are new or not the same, and the ids of those that went away.
The graph as JSON-able maps, with string keys: for a column of the
app's database (see Hakushi.Graph.Type) or a file. data goes as it
is, so it must be JSON-able itself.
The edge of an id, or nil.
The edges, in the order they were made.
The edges of a node: those that start or end at it.
Makes a graph of nodes and edges: Hakushi.Nodes and
Hakushi.Edges, or maps and keyword lists for Hakushi.Node.new/1 and
Hakushi.Edge.new/1. Raises on two nodes or two edges with one id, and
on an edge to a node the graph does not have.
The node of an id, or nil.
The nodes, in the order they are drawn.
Types
@type reason() :: :missing | :exists | :locked | :dangling | :nested
Why a change does not apply.
@type t() :: %Hakushi.Graph{ edge_order: [Hakushi.Edge.id()], edges: %{required(Hakushi.Edge.id()) => Hakushi.Edge.t()}, node_order: [Hakushi.Node.id()], nodes: %{required(Hakushi.Node.id()) => Hakushi.Node.t()} }
Functions
@spec apply(t(), Hakushi.Change.t()) :: {:ok, t(), Hakushi.Change.t(), Hakushi.Change.t()} | {:error, reason(), String.t()}
Applies a change. Gives back the graph, the change as it applied, and the change that undoes it:
- a move of a node moves the nodes in it (
parent) too, unless the change places them itself, and a move may put a node in a group or take it out (:parent); the change lists every node it moved; - a delete lists the nodes in its nodes, and the edges of all of them, which go with them;
- the change that undoes a delete adds the nodes back, with their edges (over the other nodes, as new nodes are).
A change does not apply, and nothing changes, when it names a node or an
edge that the graph does not have (:missing), adds one it has
(:exists), moves, resizes or deletes a locked node (:locked), or
adds an edge to a node it does not have, or a node to a parent it does
not have (:dangling), or puts a node in itself or in a node inside it
(:nested). The error has the id.
The box around the nodes, {x, y, width, height}, or nil for a graph
without nodes. A node without a size counts as a point.
@spec children(t(), Hakushi.Node.id()) :: [Hakushi.Node.id()]
The ids of the nodes in a node (its children), in the order they are drawn.
@spec descendants(t(), Hakushi.Node.id()) :: [Hakushi.Node.id()]
The ids of the nodes in a node, and in those, all the way down, in the order they are drawn.
@spec diff(t(), t()) :: %{ nodes: [Hakushi.Node.t()], edges: [Hakushi.Edge.t()], deleted_nodes: [Hakushi.Node.id()], deleted_edges: [Hakushi.Edge.id()] }
What changed from one graph to another: the nodes and edges that are new or not the same, and the ids of those that went away.
The graph as JSON-able maps, with string keys: for a column of the
app's database (see Hakushi.Graph.Type) or a file. data goes as it
is, so it must be JSON-able itself.
@spec edge(t(), Hakushi.Edge.id()) :: Hakushi.Edge.t() | nil
The edge of an id, or nil.
@spec edges(t()) :: [Hakushi.Edge.t()]
The edges, in the order they were made.
@spec edges_of(t(), Hakushi.Node.id()) :: [Hakushi.Edge.t()]
The edges of a node: those that start or end at it.
The graph of dump/1's maps.
Makes a graph of nodes and edges: Hakushi.Nodes and
Hakushi.Edges, or maps and keyword lists for Hakushi.Node.new/1 and
Hakushi.Edge.new/1. Raises on two nodes or two edges with one id, and
on an edge to a node the graph does not have.
@spec node(t(), Hakushi.Node.id()) :: Hakushi.Node.t() | nil
The node of an id, or nil.
@spec nodes(t()) :: [Hakushi.Node.t()]
The nodes, in the order they are drawn.