Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add engine attribute to Graph, and default to 'dot' layout #41

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,23 @@ graph graphname {
}
"""
```

# Advanced Examples

The default [layout](https://graphviz.org/docs/layouts/) used in this package in `dot`.
To change the layout, you can access the `engine` attribute of the Graph **before** showing it, or using the constructor `GraphViz.Graph` with the additional keyword attribute `engine=...`.

```
G = GraphViz.Graph("""
digraph graphname {
rankdir="LR";
x [label="{x = 3.0 | ∂x = 2.0 }", shape=record];
y [label="{y = 2.0 | ∂y = 3.0 }", shape=record];
z [label="{z = 6.0 | ∂z = 1.0 }", shape=record];
"z*" [label="*"];
x -> "z*";
y -> "z*";
"z*" -> z;
}
""", engine="dot")
```
17 changes: 9 additions & 8 deletions src/GraphViz.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ module GraphViz
mutable struct Graph
handle::Ptr{Cvoid}
didlayout::Bool
function Graph(p::Ptr{Cvoid})
this = new(p,false)
engine::String
function Graph(p::Ptr{Cvoid}, engine::String)
this = new(p,false,engine)
finalizer(free, this)
this
end
Expand All @@ -73,23 +74,23 @@ module GraphViz
g.handle = C_NULL
end

function Graph(graph::IO)
function Graph(graph::IO; engine::String = "dot")
iodisc = Ref(Agiodisc_s(
@cfunction(jl_afread,Cint,(Any,Ptr{UInt8},Cint)),
@cfunction(jl_putstr,Cint,(Any,Ptr{UInt8})),
@cfunction(jl_flush,Cint,(Any,))))
discs = Ref(Agdisc_s(cglobal((:AgMemDisc,libcgraph)),
cglobal((:AgIdDisc,libcgraph)),
Base.unsafe_convert(Ptr{Agiodisc_s}, iodisc)))
Graph(@GC.preserve iodisc ccall((:agread,libcgraph),Ptr{Cvoid},(Any,Ptr{Cvoid}),graph,discs))
Graph((@GC.preserve iodisc ccall((:agread,libcgraph),Ptr{Cvoid},(Any,Ptr{Cvoid}),graph,discs)), engine)
end
Graph(graph::Vector{UInt8}) = Graph(IOBuffer(graph))
Graph(graph::String) = @GC.preserve graph Graph(unsafe_wrap(Vector{UInt8}, graph))
Graph(graph::Vector{UInt8}, args...; kwargs...) = Graph(IOBuffer(graph), args...; kwargs...)
Graph(graph::String, args...; kwargs...) = @GC.preserve graph Graph(unsafe_wrap(Vector{UInt8}, graph), args...; kwargs...)

load(f::File{format"DOT"}) = open(Graph, f)
load(io::IO) = Graph(io)

function layout!(g::Graph;engine="neato", context = default_context[])
function layout!(g::Graph;engine=g.engine, context = default_context[])
@assert g.handle != C_NULL
if ccall((:gvLayout,libgvc),Cint,(Ptr{Cvoid},Ptr{Cvoid},Ptr{UInt8}),context.handle,g.handle,engine) == 0
g.didlayout = true
Expand Down Expand Up @@ -180,7 +181,7 @@ module GraphViz

function Base.show(io::IO, ::MIME"image/svg+xml", x::Graph)
if !x.didlayout
layout!(x,engine="neato")
layout!(x,engine=x.engine)
end
render(io,x)
end
Expand Down
36 changes: 24 additions & 12 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
using GraphViz, Cairo, Test

let g = dot"""
graph graphname {
// The label attribute can be used to change the label of a node
a [label="Foo"];
// Here, the node shape is changed.
b [shape=box];
// These edges both have different line properties
a -- b -- c [color=blue];
b -- d [style=dotted];
}
"""
@testset "Basic tests" begin
g = dot"""graph graphname {
a [label="Foo"];
b [shape=box];
a -- b -- c [color=blue];
b -- d [style=dotted];
}"""
@test_nowarn show(IOBuffer(), MIME"image/svg+xml"(), g)
@test_nowarn show(IOBuffer(), MIME"image/png"(), g)

dot_example = """graph graphname {
a [label="Foo"];
b [shape=box];
a -- b -- c [color=blue];
b -- d [style=dotted];
}"""

g = GraphViz.Graph(dot_example)
@test_nowarn show(IOBuffer(), MIME"image/svg+xml"(), g)
@test_nowarn show(IOBuffer(), MIME"image/png"(), g)
end

@testset "Engine $engine" for engine in ["dot", "neato", "fdp", "circo", "twopi", "osage", "patchwork"]
g = GraphViz.Graph(dot_example, engine=engine)
@test_nowarn show(IOBuffer(), MIME"image/svg+xml"(), g)
@test_nowarn show(IOBuffer(), MIME"image/png"(), g)
end
end