From 465aad49e31541d61b2125c82204b177db01c9f3 Mon Sep 17 00:00:00 2001 From: Abel Soares Siqueira Date: Fri, 2 Dec 2022 15:03:03 +0100 Subject: [PATCH] Add engine attribute to Graph, and default to 'dot' layout --- README.md | 20 ++++++++++++++++++++ src/GraphViz.jl | 17 +++++++++-------- test/runtests.jl | 36 ++++++++++++++++++++++++------------ 3 files changed, 53 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 4001c23..b7cd330 100644 --- a/README.md +++ b/README.md @@ -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") +``` diff --git a/src/GraphViz.jl b/src/GraphViz.jl index 3738a81..09ae356 100644 --- a/src/GraphViz.jl +++ b/src/GraphViz.jl @@ -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 @@ -73,7 +74,7 @@ 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})), @@ -81,15 +82,15 @@ module GraphViz 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 @@ -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 diff --git a/test/runtests.jl b/test/runtests.jl index d52a3e9..02bac8a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -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