diff --git a/src/Plots.jl b/src/Plots.jl index 9bb16339..ff0c7bc9 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -89,6 +89,7 @@ export OHLC, arrow, Segments, + Formatted, Animation, frame, diff --git a/src/backends/glvisualize.jl b/src/backends/glvisualize.jl index b7a097dd..a3e6f9f6 100644 --- a/src/backends/glvisualize.jl +++ b/src/backends/glvisualize.jl @@ -1053,8 +1053,8 @@ function _display(plt::Plot{GLVisualizeBackend}) GLAbstraction.center!(sp_screen) end end - yield() Reactive.post_empty() + yield() end function _show(io::IO, ::MIME"image/png", plt::Plot{GLVisualizeBackend}) diff --git a/src/components.jl b/src/components.jl index 9def1325..895f82bc 100644 --- a/src/components.jl +++ b/src/components.jl @@ -497,6 +497,13 @@ function add_arrows(func::Function, x::AVec, y::AVec) end end +# ----------------------------------------------------------------------- + +"Represents data values with formatting that should apply to the tick labels." +immutable Formatted{T} + data::T + formatter::Function +end # ----------------------------------------------------------------------- diff --git a/src/series.jl b/src/series.jl index da7b38e5..a9324053 100644 --- a/src/series.jl +++ b/src/series.jl @@ -110,7 +110,21 @@ immutable SliceIt end # the catch-all recipes @recipe function f(::Type{SliceIt}, x, y, z) - # @show "HERE", typeof((x,y,z)) + + # handle data with formatting attached + if typeof(x) <: Formatted + xformatter := x.formatter + x = x.data + end + if typeof(y) <: Formatted + yformatter := y.formatter + y = y.data + end + if typeof(z) <: Formatted + zformatter := z.formatter + z = z.data + end + xs, _ = convertToAnyVector(x, d) ys, _ = convertToAnyVector(y, d) zs, _ = convertToAnyVector(z, d) @@ -153,6 +167,33 @@ end _apply_type_recipe(d, v) = RecipesBase.apply_recipe(d, typeof(v), v)[1].args[1] +# Handle type recipes when the recipe is defined on the elements. +# This sort of recipe should return a pair of functions... one to convert to number, +# and one to format tick values. +function _apply_type_recipe(d, v::AbstractArray) + numfunc, formatter = RecipesBase.apply_recipe(d, typeof(v[1]), v[1])[1].args + Formatted(map(numfunc, v), formatter) +end + +# # special handling for Surface... need to properly unwrap and re-wrap +# function _apply_type_recipe(d, v::Surface) +# T = eltype(v.surf) +# @show T +# if T <: Integer || T <: AbstractFloat +# v +# else +# ret = _apply_type_recipe(d, v.surf) +# if typeof(ret) <: Formatted +# Formatted(Surface(ret.data), ret.formatter) +# else +# v +# end +# end +# end + +# don't do anything for ints or floats +_apply_type_recipe{T<:Union{Integer,AbstractFloat}}(d, v::AbstractArray{T}) = v + # handle "type recipes" by converting inputs, and then either re-calling or slicing @recipe function f(x, y, z) did_replace = false @@ -214,7 +255,7 @@ end @recipe f(n::Integer) = is3d(get(d,:seriestype,:path)) ? (SliceIt, n, n, n) : (SliceIt, n, n, nothing) # return a surface if this is a 3d plot, otherwise let it be sliced up -@recipe function f{T<:Number}(mat::AMat{T}) +@recipe function f{T<:Union{Integer,AbstractFloat}}(mat::AMat{T}) if all3D(d) n,m = size(mat) SliceIt, 1:m, 1:n, Surface(mat) @@ -223,6 +264,17 @@ end end end +# if a matrix is wrapped by Formatted, do similar logic, but wrap data with Surface +@recipe function f{T<:AbstractMatrix}(fmt::Formatted{T}) + if all3D(d) + mat = fmt.data + n,m = size(mat) + SliceIt, 1:m, 1:n, Formatted(Surface(mat), fmt.formatter) + else + SliceIt, nothing, fmt, nothing + end +end + # assume this is a Volume, so construct one @recipe function f{T<:Number}(vol::AbstractArray{T,3}, args...) seriestype := :volume