diff --git a/Project.toml b/Project.toml index f0ec6d3..5514858 100644 --- a/Project.toml +++ b/Project.toml @@ -6,14 +6,14 @@ version = "0.13.3" [deps] DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" Genie = "c43c736e-a2d1-11e8-161f-af95117fbd1e" -Requires = "ae029012-a4dd-5104-9daa-d747884805df" +PlotlyBase = "a03496cd-edff-5a9b-9e67-9cda94a718b5" Stipple = "4acbeb90-81a0-11ea-1966-bdaff8155998" [compat] DataFrames = "1" Genie = "5" -Requires = "1" -Stipple = "0.23, 0.24, 0.25, 0.26" +PlotlyBase = "0.8" +Stipple = "0.26" julia = "1.6" [extras] diff --git a/src/Charts.jl b/src/Charts.jl index f75e11c..2686add 100644 --- a/src/Charts.jl +++ b/src/Charts.jl @@ -9,6 +9,7 @@ import DataFrames include("Layouts.jl") using .Layouts +@reexport using PlotlyBase @reexport using .Layouts:PlotLayoutMapbox, MCenter, GeoProjection, PRotation, PlotLayoutGeo, PlotLayout, PlotAnnotation, ErrorBar, Font, ColorBar, PlotLayoutGrid, PlotLayoutAxis, PlotLayoutTitle, PlotLayoutLegend @@ -16,7 +17,6 @@ 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 @@ -57,63 +57,11 @@ const PLOT_TYPE_STREAMTUBE = "streamtube" const PLOT_TYPE_VOLUME = "volume" const PLOT_TYPE_ISOSURFACE = "isosurface" -const DEFAULT_CONFIG_TYPE = Ref{DataType}() - kebapcase(s::String) = lowercase(replace(s, r"([A-Z])" => s"-\1")) kebapcase(s::Symbol) = Symbol(kebapcase(String(s))) register_normal_element("plotly", context = @__MODULE__) -function __init__() - DEFAULT_CONFIG_TYPE[] = Charts.PlotConfig - - @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.RawType() - StructTypes.StructType(::Type{PlotlyBase.PlotConfig}) = JSON3.RawType() - JSON3.rawbytes(x::Union{PlotlyBase.HasFields,PlotlyBase.PlotConfig}) = codeunits(PlotlyBase.JSON.json(x)) - - 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 - - Stipple.stipple_parse(::Type{PlotlyBase.Plot}, d::AbstractDict) = PlotlyBase.Plot(d) - end -end - """ function plotly(p::Symbol; layout = Symbol(p, ".layout"), config = Symbol(p, ".config"), configtype = DEFAULT_CONFIG_TYPE[], kwargs...) @@ -130,8 +78,8 @@ julia> plotly(:plot, config = :config) ``` """ -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...) +function plotly(p::Symbol, args...; layout = Symbol(p, ".layout"), config = Symbol(p, ".config"), configtype = PlotlyBase.PlotConfig, kwargs...) + plot(p, args...; layout, config, configtype, kwargs...) end """ @@ -822,7 +770,7 @@ function attributes(kwargs::Union{Vector{<:Pair}, Base.Iterators.Pairs, Dict}, end function jsonrender(x) - replace(json(render(x)), "'" => raw"\'", '"' => ''') + replace(Stipple.json(render(x)), "'" => raw"\'", '"' => ''') end function plot(data::Union{Symbol,AbstractString}, args...; @@ -882,8 +830,50 @@ Base.print(io::IO, a::Union{PlotLayout, PlotConfig}) = print(io, Stipple.json(a) # ============= +Base.print(io::IO, a::Union{PlotlyBase.PlotConfig}) = print(io, Stipple.json(a)) +StructTypes.StructType(::Type{<:PlotlyBase.HasFields}) = JSON3.RawType() +StructTypes.StructType(::Type{PlotlyBase.PlotConfig}) = JSON3.RawType() +JSON3.rawbytes(x::Union{PlotlyBase.HasFields,PlotlyBase.PlotConfig}) = codeunits(PlotlyBase.JSON.json(x)) + +function Base.Dict(p::PlotlyBase.Plot) + Dict( + :data => p.data, + :layout => p.layout, + :frames => p.frames, + :config => p.config + ) +end + const PlotlyEvent = Dict{String, Any} +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 + +Stipple.stipple_parse(::Type{PlotlyBase.Plot}, d::AbstractDict) = PlotlyBase.Plot(d) + Base.@kwdef struct PlotlyEvents _selected::R{PlotlyEvent} = PlotlyEvent() _hover::R{PlotlyEvent} = PlotlyEvent() @@ -965,7 +955,7 @@ pl = PlotLayout( margin_t = 20 ) -d = JSON3.read(json(render(pl)), Dict{String, Any}) +d = JSON3.read(Stipple.json(render(pl)), Dict{String, Any}) convert(PlotLayout, d) end diff --git a/src/Layouts.jl b/src/Layouts.jl index 71bff15..9ded354 100644 --- a/src/Layouts.jl +++ b/src/Layouts.jl @@ -2,7 +2,6 @@ module Layouts using Genie, Stipple, StipplePlotly import Genie.Renderer.Html: HTMLString, normal_element, register_normal_element -using Requires const LAYOUT_TITLE_REF_CONTAINER = "container" const LAYOUT_TITLE_REF_PAPER = "paper"