Skip to content

Commit

Permalink
Add global properties
Browse files Browse the repository at this point in the history
  • Loading branch information
mikowitz committed May 11, 2018
1 parent a613f51 commit 7700e37
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 31 deletions.
53 changes: 48 additions & 5 deletions lib/graphvix/graph.ex
@@ -1,8 +1,16 @@
defmodule Graphvix.Graph do
defstruct [
digraph: nil,
global_properties: [node: [], edge: []]
]

def new do
:digraph.new()
%__MODULE__{
digraph: :digraph.new()
}
end

def digraph_tables(%__MODULE__{digraph: graph}), do: digraph_tables(graph)
def digraph_tables({:digraph, vtab, etab, ntab, _}) do
[vtab, etab, ntab]
end
Expand All @@ -11,19 +19,20 @@ defmodule Graphvix.Graph do
next_id = get_and_increment_vertex_id(graph)
attributes = Keyword.put(attributes, :label, label)
vertex_id = [:"$v" | next_id]
vid = :digraph.add_vertex(graph, vertex_id, attributes)
vid = :digraph.add_vertex(graph.digraph, vertex_id, attributes)
{graph, vid}
end

def add_edge(graph, out_from, in_to, attributes \\ []) do
eid = :digraph.add_edge(graph, out_from, in_to, attributes)
eid = :digraph.add_edge(graph.digraph, out_from, in_to, attributes)
{graph, eid}
end

def to_dot(graph) do
[
"digraph G {",
nodes_to_dot(graph),
global_properties_to_dot(graph),
vertices_to_dot(graph),
edges_to_dot(graph),
"}"
] |> Enum.reject(&is_nil/1) |> Enum.join("\n\n")
Expand All @@ -42,6 +51,40 @@ defmodule Graphvix.Graph do
{_, 0} = System.cmd("open", [filename <> ".png"])
end

def set_properties(graph, attr_for, attrs \\ []) do
Enum.reduce(attrs, graph, fn {k, v}, g ->
set_property(g, attr_for, [{k, v}])
end)
end

def set_property(graph, attr_for, [{key, value}]) do
properties = Keyword.get(graph.global_properties, attr_for)
new_props = Keyword.put(properties, key, value)
new_properties = Keyword.put(graph.global_properties, attr_for, new_props)
%{ graph | global_properties: new_properties }
end

defp global_properties_to_dot(graph) do
global_props = [
_global_properties_to_dot(graph, :node),
_global_properties_to_dot(graph, :edge)
] |> Enum.reject(&is_nil/1)

case length(global_props) do
0 -> nil
_ -> Enum.join(global_props, "\n")
end
end

defp _global_properties_to_dot(%{global_properties: global_props}, key) do
with props <- Keyword.get(global_props, key) do
case length(props) do
0 -> nil
_ -> " #{key} #{attributes_to_dot(props)}"
end
end
end

defp elements_to_dot(table, formatting_func) do
case :ets.tab2list(table) do
[] -> nil
Expand All @@ -56,7 +99,7 @@ defmodule Graphvix.Graph do
end
end

defp nodes_to_dot(graph) do
defp vertices_to_dot(graph) do
[vtab, _, _] = digraph_tables(graph)
elements_to_dot(vtab, fn {[_ | id], attributes} ->
" v#{id} #{attributes_to_dot(attributes)}"
Expand Down
47 changes: 21 additions & 26 deletions test/graphvix/graph_test.exs
Expand Up @@ -4,31 +4,6 @@ defmodule Graphvix.GraphTest do

alias Graphvix.Graph

# property "passing an atom generates a named graph" do
# check all name <- atom(:alphanumeric) do
# graph = Graph.new(name)
# assert graph.name == to_string(name)
# end
# end

# property "passing a string generates a node with a label" do
# check all name <- string(:ascii, min_length: 1) do
# graph = Graph.new(name)
# assert graph.name == name
# end
# end

# property "generating an empty dot graph" do
# check all name <- string(:ascii, min_length: 3) do
# graph = Graph.new(name)
# assert Graph.to_dot(graph) == """
# digraph "#{name}" {

# }
# """ |> String.trim
# end
# end

property "generating a graph with a vertex" do
check all label <- string(:ascii, min_length: 3)
do
Expand All @@ -44,6 +19,26 @@ defmodule Graphvix.GraphTest do
end
end

property "generating graphs with global properties" do
check all color <- string(:ascii, min_length: 3),
color2 <- string(:ascii, min_length: 3),
e_label <- string(:printable, min_length: 5)
do
graph = Graph.new()
graph = Graph.set_property(graph, :node, color: color)
graph = Graph.set_properties(graph, :edge, color: color2, label: e_label)

assert Graph.to_dot(graph) == """
digraph G {
node [color="#{color}"]
edge [label="#{e_label}",color="#{color2}"]
}
""" |> String.trim
end
end

property "adding an edge" do
check all label1 <- string(:ascii, min_length: 3),
label2 <- string(:ascii, min_length: 3)
Expand All @@ -52,7 +47,7 @@ defmodule Graphvix.GraphTest do
{graph, v1} = Graph.add_vertex(graph, label1)
{graph, v2} = Graph.add_vertex(graph, label2)
{graph, _e1} = Graph.add_edge(graph, v1, v2)
{_, _, etab, _, _} = graph
{_, _, etab, _, _} = graph.digraph
assert length(:ets.tab2list(etab)) == 1
end
end
Expand Down

0 comments on commit 7700e37

Please sign in to comment.