Skip to content

Commit

Permalink
fix rendering of JSONText again, add PlotlyBase extension, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
hhaensel committed Oct 13, 2023
1 parent b56c5fc commit bce9279
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 51 deletions.
10 changes: 9 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,20 @@ Stipple = "4acbeb90-81a0-11ea-1966-bdaff8155998"
[compat]
DataFrames = "1"
Genie = "5"
PlotlyBase = "0.8.19"
Requires = "1"
Stipple = "0.23, 0.24, 0.25, 0.26, 0.27"
julia = "1.6"

[extras]
PlotlyBase = "a03496cd-edff-5a9b-9e67-9cda94a718b5"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[extensions]
StipplePlotlyPlotlyBaseExt = "PlotlyBase"

[targets]
test = ["Test"]
test = ["Test", "PlotlyBase"]

[weakdeps]
PlotlyBase = "a03496cd-edff-5a9b-9e67-9cda94a718b5"
35 changes: 35 additions & 0 deletions ext/StipplePlotlyPlotlyBaseExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module StipplePlotlyPlotlyBaseExt

using StipplePlotly
using StipplePlotly.Stipple
using StipplePlotly.Charts

isdefined(Base, :get_extension) ? (using PlotlyBase) : (using ..PlotlyBase)

Base.print(io::IO, a::Union{PlotlyBase.PlotConfig}) = print(io, Stipple.json(a))
PlotlyBase.JSON.Writer.lower(json::Stipple.JSONText) = json.s

function Base.Dict(p::PlotlyBase.Plot)
Dict(
:data => p.data,
:layout => p.layout,
:frames => p.frames,
:config => p.config
)
end

function PlotlyBase.Plot(d::AbstractDict)
sd = symbol_dict(d)
data = haskey(sd, :data) && ! isempty(sd[:data]) ? PlotlyBase.GenericTrace.(sd[:data]) : PlotlyBase.GenericTrace[]
layout = haskey(sd, :layout) ? PlotlyBase.Layout(sd[:layout]) : PlotlyBase.Layout()
frames = haskey(sd, :frames) && ! isempty(sd[:frames]) ? PlotlyBase.PlotlyFrame.(sd[:frames]) : PlotlyBase.PlotlyFrame[]
config = haskey(sd, :config) ? PlotlyBase.PlotConfig(; sd[:config]...) : PlotlyBase.PlotConfig()

PlotlyBase.Plot(data, layout, frames; config)
end

function stipple_parse(::Type{PlotlyBase.Plot}, d::AbstractDict)
PlotlyBase.Plot(d)
end

end
58 changes: 10 additions & 48 deletions src/Charts.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ using .Layouts
using .Layouts:optionals!

import Genie.Renderer.Html: HTMLString, normal_element, register_normal_element
using Requires

export PlotLayout, PlotData, PlotAnnotation, Trace, plot, ErrorBar, Font, ColorBar, watchplot, watchplots
export PlotLayoutGrid, PlotLayoutAxis
export PlotConfig, PlotLayoutTitle, PlotLayoutLegend, PlotlyLine, PlotDataMarker
export PlotlyEvents, PlotWithEvents, PBPlotWithEvents, PlotWithEventsReadOnly, PBPlotWithEventsReadOnly
export PlotlyEvents, PlotWithEvents, PlotWithEventsReadOnly
export plotdata

const PLOT_TYPE_LINE = "scatter"
Expand Down Expand Up @@ -67,57 +66,20 @@ register_normal_element("plotly", context = @__MODULE__)

function __init__()
DEFAULT_CONFIG_TYPE[] = Charts.PlotConfig
end

@require PlotlyBase = "a03496cd-edff-5a9b-9e67-9cda94a718b5" begin
DEFAULT_CONFIG_TYPE[] = PlotlyBase.PlotConfig

Base.print(io::IO, a::Union{PlotlyBase.PlotConfig}) = print(io, Stipple.json(a))
StructTypes.StructType(::Type{<:PlotlyBase.HasFields}) = JSON3.DictType()
StructTypes.StructType(::Type{PlotlyBase.PlotConfig}) = JSON3.DictType()

function Base.Dict(p::PlotlyBase.Plot)
Dict(
:data => p.data,
:layout => p.layout,
:frames => p.frames,
:config => p.config
)
end

Base.@kwdef struct PBPlotWithEvents
var""::R{PlotlyBase.Plot} = PlotlyBase.Plot()
_selected::R{PlotlyEvent} = PlotlyEvent()
_hover::R{PlotlyEvent} = PlotlyEvent()
_click::R{PlotlyEvent} = PlotlyEvent()
_relayout::R{PlotlyEvent} = PlotlyEvent()
end

Base.@kwdef struct PBPlotWithEventsReadOnly
var""::R{PlotlyBase.Plot} = PlotlyBase.Plot(), READONLY
_selected::R{PlotlyEvent} = PlotlyEvent()
_hover::R{PlotlyEvent} = PlotlyEvent()
_click::R{PlotlyEvent} = PlotlyEvent()
_relayout::R{PlotlyEvent} = PlotlyEvent()
end

function PlotlyBase.Plot(d::AbstractDict)
sd = symbol_dict(d)
data = haskey(sd, :data) && ! isempty(sd[:data]) ? PlotlyBase.GenericTrace.(sd[:data]) : PlotlyBase.GenericTrace[]
layout = haskey(sd, :layout) ? PlotlyBase.Layout(sd[:layout]) : PlotlyBase.Layout()
frames = haskey(sd, :frames) && ! isempty(sd[:frames]) ? PlotlyBase.PlotlyFrame.(sd[:frames]) : PlotlyBase.PlotlyFrame[]
config = haskey(sd, :config) ? PlotlyBase.PlotConfig(; sd[:config]...) : PlotlyBase.PlotConfig()

PlotlyBase.Plot(data, layout, frames; config)
end

function stipple_parse(::Type{PlotlyBase.Plot}, d::AbstractDict)
PlotlyBase.Plot(d)
function default_config_type()
if DEFAULT_CONFIG_TYPE[] == Charts.PlotConfig
pkgid = Base.identify_package("PlotlyBase")
if haskey(Base.loaded_modules, pkgid)
DEFAULT_CONFIG_TYPE[] = Base.loaded_modules[pkgid].PlotConfig
end
end
DEFAULT_CONFIG_TYPE[]
end

"""
function plotly(p::Symbol; layout = Symbol(p, ".layout"), config = Symbol(p, ".config"), configtype = DEFAULT_CONFIG_TYPE[], kwargs...)
function plotly(p::Symbol; layout = Symbol(p, ".layout"), config = Symbol(p, ".config"), configtype = default_config_type(), kwargs...)
This is a convenience function for rendering a PlotlyBase.Plot or a struct with fields data, layout and config
# Example
Expand All @@ -132,7 +94,7 @@ julia> plotly(:plot, config = :config)
```
"""
function plotly(p::Symbol, args...; layout = Symbol(p, ".layout"), config = Symbol(p, ".config"), configtype = DEFAULT_CONFIG_TYPE[], kwargs...)
function plotly(p::Symbol, args...; layout = Symbol(p, ".layout"), config = Symbol(p, ".config"), configtype = default_config_type(), kwargs...)
plot("$p.data", args...; layout, config, configtype, kwargs...)
end

Expand Down
24 changes: 24 additions & 0 deletions src/StipplePlotly.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module StipplePlotly

using Genie, Stipple, Stipple.Reexport, Stipple.ParsingTools
using Requires

#===#

Expand Down Expand Up @@ -83,6 +84,29 @@ include("Layouts.jl")
function __init__()
deps_routes()
Stipple.deps!(@__MODULE__, deps)

@require PlotlyBase = "a03496cd-edff-5a9b-9e67-9cda94a718b5" begin
@static if !isdefined(Base, :get_extension)
include("../ext/StipplePlotlyPlotlyBaseExt.jl")
end

export PBPlotWithEvents, PBPlotWithEventsReadOnly
Base.@kwdef struct PBPlotWithEvents
var""::R{PlotlyBase.Plot} = PlotlyBase.Plot()
_selected::R{Charts.PlotlyEvent} = Charts.PlotlyEvent()
_hover::R{Charts.PlotlyEvent} = Charts.PlotlyEvent()
_click::R{Charts.PlotlyEvent} = Charts.PlotlyEvent()
_relayout::R{Charts.PlotlyEvent} = Charts.PlotlyEvent()
end

Base.@kwdef struct PBPlotWithEventsReadOnly
var""::R{PlotlyBase.Plot} = PlotlyBase.Plot(), READONLY
_selected::R{Charts.PlotlyEvent} = Charts.PlotlyEvent()
_hover::R{Charts.PlotlyEvent} = Charts.PlotlyEvent()
_click::R{Charts.PlotlyEvent} = Charts.PlotlyEvent()
_relayout::R{Charts.PlotlyEvent} = Charts.PlotlyEvent()
end
end
end

end # module
21 changes: 20 additions & 1 deletion test/Charts.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ function create_example_dataframe()
end

@testset "Scatter Plots" begin
@info "Test: Scatter Plots"
@testset "Multiple Groups without Tooltips" begin
df = create_example_dataframe()
pd = plotdata(df, :X, :Y; groupfeature = :Group)
Expand All @@ -17,6 +16,7 @@ end
@test isnothing(pd[1].text)
@test isnothing(pd[2].text)
end

@testset "Multiple Groups with Tooltips" begin
df = create_example_dataframe()
pd = plotdata(df, :X, :Y; groupfeature = :Group, text = df.Label)
Expand All @@ -34,4 +34,23 @@ end
@test pd[2].text[2] == "D"
end
end
end

@testset "JSONText from PlotlyBase extension" begin

using Stipple
@testset "Stipple.JSONText" begin
@test ! @isdefined PBPlotWithEvents
using PlotlyBase, PlotlyBase.JSON
@test @isdefined PBPlotWithEvents

sc = scatter(x = StipplePlotly.JSONText("jsontext"), more_of_this = "a")
pl = Plot(sc)
@test JSON.json(sc) == "{\"type\":\"scatter\",\"more\":{\"of\":{\"this\":\"a\"}},\"x\":\"jsontext\"}"
@test contains(JSON.json(pl), "{\"type\":\"scatter\",\"more\":{\"of\":{\"this\":\"a\"}},\"x\":\"jsontext\"}")

@test Stipple.json(sc) == "{\"type\":\"scatter\",\"more\":{\"of\":{\"this\":\"a\"}},\"x\":\"jsontext\"}"
@test contains(Stipple.json(pl), "{\"type\":\"scatter\",\"more\":{\"of\":{\"this\":\"a\"}},\"x\":\"jsontext\"}")
end

end
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ using StipplePlotly
using Test
using DataFrames

@testset "StipplePlotly.jl" begin
@testset verbose = true "Charts" begin

include("Charts.jl")

Expand Down

0 comments on commit bce9279

Please sign in to comment.