Skip to content

Commit 1c5738c

Browse files
authored
Merge pull request #35 from oschulz/render-functions
Allow for passing functions for text, tooltip, etc.
2 parents 06b93f2 + d561961 commit 1c5738c

File tree

4 files changed

+81
-17
lines changed

4 files changed

+81
-17
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "D3Trees"
22
uuid = "e3df1716-f71e-5df9-9e2d-98e193103c45"
33
repo = "https://github.com/sisl/D3Trees.jl.git"
4-
version = "0.3.4"
4+
version = "0.3.5"
55

66
[deps]
77
# Blink - not compatible with HTTP.jl v1 yet

src/D3Trees.jl

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct D3Tree
2626
link_style::Vector{String}
2727
title::String
2828
options::Dict{Symbol,Any}
29+
frender::NamedTuple{(:text, :tooltip, :style, :link_style)}
2930
end
3031

3132
"""
@@ -92,10 +93,10 @@ Construct a tree to be displayed using D3 in a browser or ipython notebook, spec
9293
creates a tree with four nodes. Nodes 2 and 3 are children of node 1, and node 4 is the only child of node 3. Nodes 2 and 4 are childless.
9394
9495
## Keyword:
95-
- `text::Vector{String}` - text to appear under each node.
96-
- `tooltip::Vector{String}` - text to appear when hovering over each node.
97-
- `style::Vector{String}` - html style for each node.
98-
- `link_style::Vector{String}` - html style for each link.
96+
- `text::Union{AbstractVector{<:AbstractString},Base.Callable}` - text to appear under each node, resp. a function `text(node)` to generate it.
97+
- `tooltip::Union{AbstractVector{<:AbstractString},Base.Callable}` - text to appear when hovering over each node or a function.
98+
- `style::Union{AbstractVector{<:AbstractString},Base.Callable}` - html style for each node or a function.
99+
- `link_style::Union{AbstractVector{<:AbstractString},Base.Callable}` - html style for each link or a function.
99100
- `title::String` - html title.
100101
- `init_expand::Integer`: (default `0`) - levels to expand initially.
101102
- `init_duration::Number`: (default `750`) - duration of the initial animation in ms.
@@ -106,14 +107,64 @@ Construct a tree to be displayed using D3 in a browser or ipython notebook, spec
106107
function D3Tree(children::AbstractVector{<:AbstractVector}; kwargs...)
107108
kwd = Dict(kwargs)
108109
n = length(children)
110+
111+
v_text, f_text = if haskey(kwd, :text)
112+
kw_text = kwd[:text]
113+
if kw_text isa Base.AbstractVector
114+
convert(Vector{String}, kw_text), text
115+
elseif kw_text isa Base.Callable
116+
fill("", n), kw_text
117+
else
118+
throw(ArgumentError("D3Tree kwwarg text must be an AbstractVector{<:AbstractString} or a Base.Callable"))
119+
end
120+
else
121+
collect(string(i) for i in 1:n), text
122+
end
123+
124+
v_tooltip, f_tooltip = if haskey(kwd, :tooltip)
125+
kw_tooltip = kwd[:tooltip]
126+
if kw_tooltip isa Base.AbstractVector
127+
convert(Vector{String}, kw_tooltip), tooltip
128+
elseif kw_tooltip isa Base.Callable
129+
fill("", n), kw_tooltip
130+
else throw(ArgumentError("D3Tree kwwarg tooltip must be an AbstractVector{<:AbstractString} or a Base.Callable"))
131+
end
132+
else
133+
fill("", n), tooltip
134+
end
135+
136+
v_style, f_style = if haskey(kwd, :style)
137+
kw_style = kwd[:style]
138+
if kw_style isa Base.AbstractVector
139+
convert(Vector{String}, kw_style), style
140+
elseif kw_style isa Base.Callable
141+
fill("", n), kw_style
142+
else throw(ArgumentError("D3Tree kwwarg style must be an AbstractVector{<:AbstractString} or a Base.Callable"))
143+
end
144+
else
145+
fill("", n), style
146+
end
147+
148+
v_link_style, f_link_style = if haskey(kwd, :link_style)
149+
kw_link_style = kwd[:link_style]
150+
if kw_link_style isa Base.AbstractVector
151+
convert(Vector{String}, kw_link_style), link_style
152+
elseif kw_link_style isa Base.Callable
153+
fill("", n), kw_link_style
154+
else throw(ArgumentError("D3Tree kwwarg link_style must be an AbstractVector{<:AbstractString} or a Base.Callable"))
155+
end
156+
else
157+
fill("", n), link_style
158+
end
159+
160+
frender = (text = f_text, tooltip = f_tooltip, style = f_style, link_style = f_link_style)
161+
109162
return D3Tree(children,
110163
Dict(),
111-
get(kwd, :text, collect(string(i) for i in 1:n)),
112-
get(kwd, :tooltip, fill("", n)),
113-
get(kwd, :style, fill("", n)),
114-
get(kwd, :link_style, fill("", n)),
164+
v_text, v_tooltip, v_style, v_link_style,
115165
get(kwd, :title, "Julia D3Tree"),
116166
convert(Dict{Symbol,Any}, kwd),
167+
frender,
117168
)
118169
end
119170

@@ -183,10 +234,10 @@ function push_node!(t::D3Tree, node, lazy_expand_after_depth::Int, node_dict=not
183234
end
184235

185236
push!(t.children, Int[])
186-
push!(t.text, text(node))
187-
push!(t.tooltip, tooltip(node))
188-
push!(t.style, style(node))
189-
push!(t.link_style, link_style(node))
237+
push!(t.text, t.frender.text(node))
238+
push!(t.tooltip, t.frender.tooltip(node))
239+
push!(t.style, t.frender.style(node))
240+
push!(t.link_style, t.frender.link_style(node))
190241

191242
if lazy_expand_after_depth > 0
192243
for c in children(node)
@@ -219,7 +270,8 @@ struct D3OffsetSubtree
219270
subtree.style[2:end],
220271
subtree.link_style[2:end],
221272
subtree.title,
222-
subtree.options
273+
subtree.options,
274+
subtree.frender
223275
)
224276
new(root_children, offset_subtree, root_id)
225277
end
@@ -234,7 +286,7 @@ function expand_node!(t::D3Tree, ind::Int, lazy_expand_after_depth::Int)
234286
node = pop!(t.unexpanded_children, ind)
235287

236288
# TODO: also pass other options from t?
237-
subtree = D3Tree(node; lazy_expand_after_depth=lazy_expand_after_depth)
289+
subtree = D3Tree(node; lazy_expand_after_depth=lazy_expand_after_depth, t.options...)
238290
offset = length(t.children) - 1
239291

240292
offset_subtree = D3OffsetSubtree(ind, subtree, offset)

src/show.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
Convert datastructure to json, shift indeces to zero-indexing for use in javascript
33
"""
44
function JSON.json(t::D3Tree)
5-
data = Dict(key => getfield(t, key) for key fieldnames(D3Tree))
5+
fields = (:children, :unexpanded_children, :text, :tooltip, :style, :link_style, :title)
6+
data = Dict(key => getfield(t, key) for key fields)
67
data[:children] = [Int[ind - 1 for ind list] for list data[:children]]
78
data[:unexpanded_children] = Int[k - 1 for k keys(data[:unexpanded_children])]
89
return json(data)
@@ -12,7 +13,8 @@ end
1213
Convert datastructure to json, shift indeces to zero-indexing for use in javascript
1314
"""
1415
function JSON.json(st::D3OffsetSubtree)
15-
data = Dict(key => getfield(st.subtree, key) for key fieldnames(D3Tree))
16+
fields = (:children, :unexpanded_children, :text, :tooltip, :style, :link_style, :title)
17+
data = Dict(key => getfield(st.subtree, key) for key fields)
1618

1719
data[:root_children] = Int[ind - 1 for ind st.root_children]
1820
data[:root_id] = st.root_id - 1

test/runtests.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ include("binary_abstract_trees.jl")
3333
svg_height=300
3434
)
3535

36+
t3 = D3Tree(children,
37+
text=(node -> string(node)),
38+
style=(node -> ""),
39+
tooltip=(node -> "tooltip"),
40+
link_style=(node -> ""),
41+
init_expand=1000,
42+
init_duration=5000,
43+
svg_height=300
44+
)
45+
3646
# inchrome(t1)
3747
# inbrowser(t1, "firefox")
3848
# inchrome(t2)

0 commit comments

Comments
 (0)