backend template renaming/reorg/cleanup, pyplot fixes

This commit is contained in:
Thomas Breloff 2016-05-23 10:29:35 -04:00
parent d4d388a94b
commit ef0d99340a
20 changed files with 488 additions and 954 deletions

View File

@ -51,6 +51,7 @@ like_line(seriestype::Symbol) = seriestype in (:line, :path, :steppre, :ste
like_surface(seriestype::Symbol) = seriestype in (:contour, :contour3d, :heatmap, :surface, :wireframe, :image)
is3d(seriestype::Symbol) = seriestype in _3dTypes
is3d(series::Series) = is3d(series.d)
is3d(d::KW) = trueOrAllTrue(is3d, d[:seriestype])
const _allStyles = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]

View File

@ -53,10 +53,10 @@ _update_plot(pkg::AbstractBackend, plt::Plot, d::KW) = error("_update_plot($pkg
# don't do anything as a default
_create_backend_figure(plt::Plot) = nothing
_before_add_series(plt::Plot) = nothing
_add_series(plt::Plot) = nothing
_add_annotations{X,Y,V}(plt::Plot, anns::AVec{Tuple{X,Y,V}}) = nothing
_update_plot_pos_size(plt::AbstractPlot, d::KW) = nothing
_before_update(plt::Plot) = nothing
_series_added(plt::Plot) = nothing
# _add_annotations{X,Y,V}(plt::Plot, anns::AVec{Tuple{X,Y,V}}) = nothing
# _update_plot_pos_size(plt::AbstractPlot, d::KW) = nothing
# ---------------------------------------------------------

View File

@ -79,13 +79,6 @@ function _initialize_backend(::BokehBackend; kw...)
end
end
# make255(x) = round(Int, 255 * x)
# function bokehcolor(c::Colorant)
# @sprintf("rgba(%d, %d, %d, %1.3f)", [make255(f(c)) for f in [red,green,blue]]..., alpha(c))
# end
# bokehcolor(cs::ColorScheme) = bokehcolor(getColor(cs))
const _glyphtypes = KW(
:ellipse => :Circle,
@ -154,8 +147,8 @@ function _create_backend_figure(plt::Plot{BokehBackend})
end
# function _add_series(::BokehBackend, plt::Plot, d::KW)
function _add_series(plt::Plot{BokehBackend}, series::Series)
# function _series_added(::BokehBackend, plt::Plot, d::KW)
function _series_added(plt::Plot{BokehBackend}, series::Series)
bdata = Dict{Symbol, Vector}(:x => collect(series.d[:x]), :y => collect(series.d[:y]))
glyph = Bokeh.Bokehjs.Glyph(
@ -180,9 +173,6 @@ end
function _update_plot(plt::Plot{BokehBackend}, d::KW)
end
function _update_plot_pos_size(plt::AbstractPlot{BokehBackend}, d::KW)
end
# ----------------------------------------------------------------
# accessors for x/y data
@ -199,29 +189,9 @@ end
# end
# ----------------------------------------------------------------
function _add_annotations{X,Y,V}(plt::Plot{BokehBackend}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
# TODO: add the annotation to the plot
end
end
# ----------------------------------------------------------------
# function _create_subplot(subplt::Subplot{BokehBackend}, isbefore::Bool)
# # TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
#
# end
function _expand_limits(lims, plt::Plot{BokehBackend}, isx::Bool)
# TODO: call expand limits for each plot data
end
function _remove_axis(plt::Plot{BokehBackend}, isx::Bool)
# TODO: if plot is inner subplot, might need to remove ticks or axis labels
end
# ----------------------------------------------------------------

View File

@ -580,8 +580,8 @@ end
# plot one data series
# function _add_series(::GadflyBackend, plt::Plot, d::KW)
function _add_series(plt::Plot{GadflyBackend}, series::Series)
# function _series_added(::GadflyBackend, plt::Plot, d::KW)
function _series_added(plt::Plot{GadflyBackend}, series::Series)
# first clear out the temporary layer
gplt = getGadflyContext(plt)
if gplt.layers[1].geom.tag == :remove

View File

@ -95,8 +95,8 @@ function _create_backend_figure(plt::Plot{GLVisualizeBackend})
end
# function _add_series(::GLVisualizeBackend, plt::Plot, d::KW)
function _add_series(plt::Plot{GLVisualizeBackend}, series::Series)
# function _series_added(::GLVisualizeBackend, plt::Plot, d::KW)
function _series_added(plt::Plot{GLVisualizeBackend}, series::Series)
# TODO: add one series to the underlying package
# push!(plt.seriesargs, d)
# TODO: this should be moved to the display method?

View File

@ -873,7 +873,7 @@ end
# Plot(nothing, pkg, 0, d, KW[])
# end
# function _add_series(::GRBackend, plt::Plot, d::KW)
# function _series_added(::GRBackend, plt::Plot, d::KW)
# push!(plt.seriesargs, d)
# plt
# end

View File

@ -42,13 +42,13 @@ end
# # plot one data series
# function _add_series(::ImmerseBackend, plt::Plot, d::KW)
# function _series_added(::ImmerseBackend, plt::Plot, d::KW)
# addGadflySeries!(plt, d)
# push!(plt.seriesargs, d)
# plt
# end
function _add_series(plt::Plot{ImmerseBackend}, series::Series)
function _series_added(plt::Plot{ImmerseBackend}, series::Series)
addGadflySeries!(plt, series.d)
end

View File

@ -238,7 +238,7 @@ end
# end
# function _add_series(::PGFPlotsBackend, plt::Plot, d::KW)
# function _series_added(::PGFPlotsBackend, plt::Plot, d::KW)
# # TODO: add one series to the underlying package
# push!(plt.seriesargs, d)
# plt

View File

@ -91,7 +91,7 @@ end
# end
# function _add_series(::PlotlyBackend, plt::Plot, d::KW)
# function _series_added(::PlotlyBackend, plt::Plot, d::KW)
# # TODO: add one series to the underlying package
# push!(plt.seriesargs, d)
# plt

View File

@ -113,7 +113,7 @@ function _create_backend_figure(plt::Plot{PlotlyJSBackend})
end
function _add_series(plt::Plot{PlotlyJSBackend}, series::Series)
function _series_added(plt::Plot{PlotlyJSBackend}, series::Series)
d = series.d
syncplot = plt.o

File diff suppressed because it is too large Load Diff

View File

@ -137,8 +137,8 @@ function _create_backend_figure(plt::Plot{QwtBackend})
# plt
end
# function _add_series(::QwtBackend, plt::Plot, d::KW)
function _add_series(plt::Plot{QwtBackend}, series::Series)
# function _series_added(::QwtBackend, plt::Plot, d::KW)
function _series_added(plt::Plot{QwtBackend}, series::Series)
d = adjustQwtKeywords(plt, false; series.d...)
fixcolors(d)
dumpdict(d,"\n\n!!! plot!")

View File

@ -1,84 +1,74 @@
# TODO: find/replace all [PkgName] with CamelCase, all [pkgname] with lowercase
# TODO: find/replace all [PkgName] with CamelCase
# [WEBSITE]
# [ADD BACKEND WEBSITE]
function _initialize_backend(::[PkgName]AbstractBackend; kw...)
@eval begin
import [PkgName]
export [PkgName]
# TODO: other initialization that needs to be eval-ed
end
# TODO: other initialization
@eval begin
import [PkgName]
export [PkgName]
# todo: other initialization that needs to be eval-ed
end
# todo: other initialization
end
# ---------------------------------------------------------------------------
# Create the window/figure for this backend.
function _create_backend_figure(plt::Plot{[PkgName]Backend})
# TODO: create the window/figure for this backend
nothing
end
function _add_series(plt::Plot{[PkgName]Backend}, series::Series)
# TODO: add one series to the underlying package
# Set up the subplot within the backend object.
function _initialize_subplot(plt::Plot{PyPlotBackend}, sp::Subplot{PyPlotBackend})
end
# function _add_annotations{X,Y,V}(plt::Plot{[PkgName]AbstractBackend}, anns::AVec{@compat(Tuple{X,Y,V})})
# for ann in anns
# # TODO: add the annotation to the plot
# end
# end
# Set the (left, top, right, bottom) minimum padding around the plot area
# to fit ticks, tick labels, guides, colorbars, etc.
function _update_min_padding!(sp::Subplot{[PkgName]Backend})
sp.minpad = (20mm, 5mm, 2mm, 10mm)
end
# Use the bounding boxes (and methods left/top/right/bottom/width/height) `sp.bbox` and `sp.plotarea` to
# position the subplot in the backend.
function _update_position!(sp::Subplot{[PkgName]Backend})
end
# ----------------------------------------------------------------
function _before_update_plot(plt::Plot{[PkgName]AbstractBackend})
# This is called before series processing... use it if you need to make the backend object current or something.
function _before_update(plt::Plot{[PkgName]AbstractBackend})
end
# TODO: override this to update plot items (title, xlabel, etc) after creation
# Add one series to the underlying backend object.
function _series_added(plt::Plot{[PkgName]Backend}, series::Series)
end
# Override this to update plot items (title, xlabel, etc), and add annotations (d[:annotations])
function _update_plot(plt::Plot{[PkgName]AbstractBackend}, d::KW)
end
function _update_plot_pos_size(plt::AbstractPlot{[PkgName]AbstractBackend}, d::KW)
# ----------------------------------------------------------------
# When series data is added/changed, this callback can do dynamic updates to the backend object.
# note: if the backend rebuilds the plot from scratch on display, then you might not do anything here.
function _series_updated(plt::Plot{[PkgName]AbstractBackend}, series::Series)
end
# ----------------------------------------------------------------
# accessors for x/y data
# function getxy(plt::Plot{[PkgName]AbstractBackend}, i::Int)
# # TODO: return a tuple of (x, y) vectors
# end
#
# function setxy!{X,Y}(plt::Plot{[PkgName]AbstractBackend}, xy::Tuple{X,Y}, i::Integer)
# # TODO: set the plot data from the (x,y) tuple
# plt
# end
# ----------------------------------------------------------------
# function _create_subplot(subplt::Subplot{[PkgName]AbstractBackend}, isbefore::Bool)
# # TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
# end
# function _expand_limits(lims, plt::Plot{[PkgName]AbstractBackend}, isx::Bool)
# # TODO: call expand limits for each plot data
# end
#
# function _remove_axis(plt::Plot{[PkgName]AbstractBackend}, isx::Bool)
# # TODO: if plot is inner subplot, might need to remove ticks or axis labels
# end
# ----------------------------------------------------------------
# Write a png to io. You could define methods for:
# "application/eps" => "eps",
# "image/eps" => "eps",
# "application/pdf" => "pdf",
# "image/png" => "png",
# "application/postscript" => "ps",
# "image/svg+xml" => "svg"
function Base.writemime(io::IO, ::MIME"image/png", plt::AbstractPlot{[PkgName]AbstractBackend})
# TODO: write a png to io
end
# Display/show the plot (open a GUI window, or browser page, for example).
function Base.display(::PlotsDisplay, plt::Plot{[PkgName]AbstractBackend})
# TODO: display/show the plot
end
# function Base.display(::PlotsDisplay, plt::Subplot{[PkgName]AbstractBackend})
# # TODO: display/show the subplot
# end

View File

@ -195,7 +195,7 @@ function _create_backend_figure(plt::Plot{UnicodePlotsBackend})
# plt
end
function _add_series(plt::Plot{UnicodePlotsBackend}, series::Series)
function _series_added(plt::Plot{UnicodePlotsBackend}, series::Series)
d = series.d
# TODO don't need these once the "bar" series recipe is done
if d[:seriestype] in (:sticks, :bar)

View File

@ -96,7 +96,7 @@ end
:star5 => "asterisk"
)
function _before_add_series(plt::Plot{WinstonBackend})
function _before_update(plt::Plot{WinstonBackend})
Winston.ghf(plt.o)
end
@ -127,7 +127,7 @@ function getWinstonItems(plt::Plot)
window, canvas, wplt
end
function _add_series(plt::Plot{WinstonBackend}, series::Series)
function _series_added(plt::Plot{WinstonBackend}, series::Series)
d = series.d
window, canvas, wplt = getWinstonItems(plt)

View File

@ -5,6 +5,8 @@
const px = AbsoluteLength(0.254)
const pct = Length{:pct, Float64}(1.0)
const _cbar_width = 5mm
Base.(:.*)(m::Measure, n::Number) = m * n
Base.(:.*)(n::Number, m::Measure) = m * n
Base.(:-)(m::Measure, a::AbstractArray) = map(ai -> m - ai, a)
@ -65,6 +67,15 @@ function crop(parent::BoundingBox, child::BoundingBox)
BoundingBox(l, t, w, h)
end
# convert a bounding box from absolute coords to percentages... returns an array of percentages of figure size: [left, bottom, width, height]
function bbox_to_pcts(bb::BoundingBox, figw, figh, flipy = true)
mms = Float64[f(bb).value for f in (left,bottom,width,height)]
if flipy
mms[2] = figh.value - mms[2] # flip y when origin in bottom-left
end
mms ./ Float64[figw.value, figh.value, figw.value, figh.value]
end
function Base.show(io::IO, bbox::BoundingBox)
print(io, "BBox{l,t,r,b,w,h = $(left(bbox)),$(top(bbox)), $(right(bbox)),$(bottom(bbox)), $(width(bbox)),$(height(bbox))}")
end
@ -93,7 +104,7 @@ padding_w(layout::AbstractLayout) = left_padding(layout) + right_padding(layout)
padding_h(layout::AbstractLayout) = bottom_padding(layout) + top_padding(layout)
padding(layout::AbstractLayout) = (padding_w(layout), padding_h(layout))
update_position!(layout::AbstractLayout) = nothing
_update_position!(layout::AbstractLayout) = nothing
update_child_bboxes!(layout::AbstractLayout) = nothing
width(layout::AbstractLayout) = width(layout.bbox)
@ -105,6 +116,11 @@ attr(layout::AbstractLayout, k::Symbol, v) = get(layout.attr, k, v)
attr!(layout::AbstractLayout, v, k::Symbol) = (layout.attr[k] = v)
hasattr(layout::AbstractLayout, k::Symbol) = haskey(layout.attr, k)
leftpad(layout::AbstractLayout) = 0mm
toppad(layout::AbstractLayout) = 0mm
rightpad(layout::AbstractLayout) = 0mm
bottompad(layout::AbstractLayout) = 0mm
# -----------------------------------------------------------
# RootLayout
@ -138,6 +154,7 @@ Base.getindex(layout::EmptyLayout, r::Int, c::Int) = nothing
# nested, gridded layout with optional size percentages
type GridLayout <: AbstractLayout
parent::AbstractLayout
minpad::Tuple # leftpad, toppad, rightpad, bottompad
bbox::BoundingBox
grid::Matrix{AbstractLayout} # Nested layouts. Each position is a AbstractLayout, which allows for arbitrary recursion
widths::Vector{Measure}
@ -155,6 +172,7 @@ function GridLayout(dims...;
grid = Matrix{AbstractLayout}(dims...)
layout = GridLayout(
parent,
(20mm, 5mm, 2mm, 10mm),
defaultbox,
grid,
Measure[w*pct for w in widths],
@ -173,13 +191,39 @@ function Base.setindex!(layout::GridLayout, v, r::Int, c::Int)
layout.grid[r,c] = v
end
min_padding_left(layout::GridLayout) = maximum(map(min_padding_left, layout.grid[:,1]))
min_padding_top(layout::GridLayout) = maximum(map(min_padding_top, layout.grid[1,:]))
min_padding_right(layout::GridLayout) = maximum(map(min_padding_right, layout.grid[:,end]))
min_padding_bottom(layout::GridLayout) = maximum(map(min_padding_bottom, layout.grid[end,:]))
leftpad(layout::GridLayout) = layout.minpad[1]
toppad(layout::GridLayout) = layout.minpad[2]
rightpad(layout::GridLayout) = layout.minpad[3]
bottompad(layout::GridLayout) = layout.minpad[4]
# min_padding_left(layout::GridLayout) = maximum(map(min_padding_left, layout.grid[:,1]))
# min_padding_top(layout::GridLayout) = maximum(map(min_padding_top, layout.grid[1,:]))
# min_padding_right(layout::GridLayout) = maximum(map(min_padding_right, layout.grid[:,end]))
# min_padding_bottom(layout::GridLayout) = maximum(map(min_padding_bottom, layout.grid[end,:]))
update_position!(layout::GridLayout) = map(update_position!, layout.grid)
# leftpad, toppad, rightpad, bottompad
function _update_min_padding!(layout::GridLayout)
# minpad_matrix = map(_update_min_padding!, layout.grid)
# nr,nc = size(layout)
# leftpad = maximum([minpad_matrix[r,1][1] for r=1:nr])
# toppad = maximum([minpad_matrix[1,c][2] for c=1:nc])
# rightpad = maximum([minpad_matrix[r,end][3] for r=1:nr])
# bottompad = maximum([minpad_matrix[end,c][4] for c=1:nc])
map(_update_min_padding!, layout.grid)
layout.minpad = (
maximum(map(leftpad, layout.grid[:,1])),
maximum(map(toppad, layout.grid[1,:])),
maximum(map(rightpad, layout.grid[:,end])),
maximum(map(bottompad, layout.grid[end,:]))
)
# layout.minpad = (leftpad, toppad, rightpad, bottompad)
end
function _update_position!(layout::GridLayout)
map(_update_position!, layout.grid)
end
# recursively compute the bounding boxes for the layout and plotarea (relative to canvas!)
@ -187,10 +231,16 @@ function update_child_bboxes!(layout::GridLayout)
nr, nc = size(layout)
# create a matrix for each minimum padding direction
minpad_left = map(min_padding_left, layout.grid)
minpad_top = map(min_padding_top, layout.grid)
minpad_right = map(min_padding_right, layout.grid)
minpad_bottom = map(min_padding_bottom, layout.grid)
_update_min_padding!(layout)
# minpad_left = map(l -> l.minpad[1], layout.grid)
# minpad_left = map(min_padding_left, layout.grid)
# minpad_top = map(min_padding_top, layout.grid)
# minpad_right = map(min_padding_right, layout.grid)
# minpad_bottom = map(min_padding_bottom, layout.grid)
minpad_left = map(leftpad, layout.grid)
minpad_top = map(toppad, layout.grid)
minpad_right = map(rightpad, layout.grid)
minpad_bottom = map(bottompad, layout.grid)
# @show minpad_left minpad_top minpad_right minpad_bottom
# get the max horizontal (left and right) padding over columns,

View File

@ -94,9 +94,7 @@ end
# natively by the backend
function _apply_series_recipe(plt::Plot, d::KW)
st = d[:seriestype]
# dumpdict(d, "apply_series_recipe", true)
if st in supportedTypes()
# println("adding series!!")
# getting ready to add the series... last update to subplot from anything
# that might have been added during series recipes
@ -134,7 +132,7 @@ function _apply_series_recipe(plt::Plot, d::KW)
warnOnUnsupported(plt.backend, d)
series = Series(d)
push!(plt.series_list, series)
_add_series(plt, series)
_series_added(plt, series)
else
# get a sub list of series for this seriestype
@ -158,7 +156,7 @@ end
# note: at entry, we only have those preprocessed args which were passed in... no default values yet
function _plot!(plt::Plot, d::KW, args...)
# just in case the backend needs to set up the plot (make it current or something)
_before_add_series(plt)
_before_update(plt)
# first apply any args for the subplots
for (idx,sp) in enumerate(plt.subplots)
@ -172,15 +170,6 @@ function _plot!(plt::Plot, d::KW, args...)
args = tuple(extractGroupArgs(d[:group], args...), args...)
end
# # initialize the annotations list with what was passed in
# # TODO: there must be cleaner way to handle this!
# anns = annotations(get(d, :annotation, NTuple{3}[]))
# if typeof(anns) <: AVec{PlotText}
# anns = NTuple{3}[]
# else
# delete!(d, :annotation)
# end
# for plotting recipes, swap out the args and update the parameter dictionary
# we are keeping a queue of series that still need to be processed.
@ -212,7 +201,6 @@ function _plot!(plt::Plot, d::KW, args...)
# if there was a grouping, filter the data here
_filter_input_data!(kw)
# @show typeof((kw[:x], kw[:y], kw[:z]))
# map marker_z if it's a Function
if isa(get(kw, :marker_z, nothing), Function)
@ -250,38 +238,9 @@ function _plot!(plt::Plot, d::KW, args...)
# !!! note: at this point, kw_list is fully decomposed into individual series... one KW per series !!!
# # TODO: move annotations into subplot update
# # now include any annotations which were added during recipes
# for kw in kw_list
# append!(anns, annotations(pop!(kw, :annotation, [])))
# end
# # @show anns
# for kw in kw_list
# @show typeof((kw[:x], kw[:y], kw[:z]))
# end
# # merge plot args... this is where we combine all the plot args from the user and
# # from the recipes... axis info, colors, etc
# # TODO: why do i need to check for the subplot key?
# # if !haskey(d, :subplot)
# # for kw in vcat(kw_list, d)
# for kw in kw_list
# _update_subplot_args(plt, kw[:subplot], kw)
# # _add_plotargs!(plt, kw)
# end
# # handlePlotColors(plt.backend, plt.plotargs)
# # end
# for kw in kw_list
# @show typeof((kw[:x], kw[:y], kw[:z]))
# end
# this is it folks!
# TODO: we probably shouldn't use i for tracking series index, but rather explicitly track it in recipes
for (i,kw) in enumerate(kw_list)
# DD(kw, "series $i before")
if !(get(kw, :seriestype, :none) in (:xerror, :yerror))
plt.n += 1
end
@ -309,16 +268,10 @@ function _plot!(plt::Plot, d::KW, args...)
sp.attr[:annotations] = vcat(sp_anns, anns)
# we update subplot args in case something like the color palatte is part of the recipe
# DD(sp.attr[:xaxis].d, "before USA $i")
# DD(kw, "kw")
_update_subplot_args(plt, sp, kw, idx)
# DD(sp.attr[:xaxis].d, "after USA $i")
# set default values, select from attribute cycles, and generally set the final attributes
_add_defaults!(kw, plt, sp, i)
# DD(kw, "series $i after")
#
# now we have a fully specified series, with colors chosen. we must recursively handle
# series recipes, which dispatch on seriestype. If a backend does not natively support a seriestype,
@ -326,14 +279,9 @@ function _plot!(plt::Plot, d::KW, args...)
# For example, a histogram is just a bar plot with binned data, a bar plot is really a filled step plot,
# and a step plot is really just a path. So any backend that supports drawing a path will implicitly
# be able to support step, bar, and histogram plots (and any recipes that use those components).
# DD(sp.attr[:xaxis].d, "before $i")
_apply_series_recipe(plt, kw)
# DD(sp.attr[:xaxis].d, "after $i")
end
# # now that we're done adding all the series, add the annotations
# _add_annotations(plt, anns)
# TODO just need to pass plt... and we should do all non-series updates here
_update_plot(plt, plt.plotargs)
@ -348,18 +296,6 @@ function _plot!(plt::Plot, d::KW, args...)
plt
end
# # handle the grouping
# function _add_series(plt::Plot, d::KW, groupby::GroupBy, args...)
# starting_n = plt.n
# for (i, glab) in enumerate(groupby.groupLabels)
# tmpd = copy(d)
# tmpd[:numUncounted] = plt.n - starting_n
# _add_series(plt, tmpd, nothing, args...;
# idxfilter = groupby.groupIds[i],
# grouplabel = string(glab))
# end
# end
function _replace_linewidth(d::KW)
# get a good default linewidth... 0 for surface and heatmaps
@ -368,63 +304,6 @@ function _replace_linewidth(d::KW)
end
end
# # no grouping
# function _add_series(plt::Plot, d::KW, args...;
# idxfilter = nothing,
# grouplabel = "")
#
# # get the list of dictionaries, one per series
# dumpdict(d, "before process_inputs")
# process_inputs(plt, d, args...)
# dumpdict(d, "after process_inputs")
#
# if idxfilter != nothing
# # add the group name as the label if there isn't one passed in
# get!(d, :label, grouplabel)
# # filter the data
# filter_data!(d, idxfilter)
# end
# # dumpdict(d,"",true)
#
# seriesArgList, xmeta, ymeta = build_series_args(plt, d) #, idxfilter)
# # seriesArgList, xmeta, ymeta = build_series_args(plt, groupargs..., args...; d...)
#
# # # if we were able to extract guide information from the series inputs, then update the plot
# # # @show xmeta, ymeta
# # updateDictWithMeta(d, plt.plotargs, xmeta, true)
# # updateDictWithMeta(d, plt.plotargs, ymeta, false)
#
#
# # function _add_series(plt::Plot, ds::)
# # now we can plot the series
# for (i,di) in enumerate(seriesArgList)
# plt.n += 1
#
# if !stringsSupported() && di[:seriestype] != :pie
# setTicksFromStringVector(plt, d, di, "x")
# setTicksFromStringVector(plt, d, di, "y")
# setTicksFromStringVector(plt, d, di, "z")
# end
#
# # remove plot args
# for k in keys(_plot_defaults)
# delete!(di, k)
# end
#
# # merge in plotarg_overrides
# plotarg_overrides = pop!(di, :plotarg_overrides, nothing)
# if plotarg_overrides != nothing
# merge!(plt.plotargs, plotarg_overrides)
# end
# # dumpdict(plt.plotargs, "pargs", true)
#
# dumpdict(di, "Series $i")
#
# _replace_linewidth(di)
#
# _add_series(plt.backend, plt, di)
# end
# end
# --------------------------------------------------------------------
@ -482,54 +361,11 @@ end
# end
# --------------------------------------------------------------------
# TODO: remove
# # should we update the x/y label given the meta info during input slicing?
# function updateDictWithMeta(d::KW, plotargs::KW, meta::Symbol, isx::Bool)
# lsym = isx ? :xguide : :yguide
# if plotargs[lsym] == default(lsym)
# d[lsym] = string(meta)
# end
# end
# updateDictWithMeta(d::KW, plotargs::KW, meta, isx::Bool) = nothing
# --------------------------------------------------------------------
annotations(::Void) = []
annotations(anns::AVec) = anns
annotations(anns) = Any[anns]
# annotations{X,Y,V}(v::AVec{@compat(Tuple{X,Y,V})}) = v
# annotations{X,Y,V}(t::@compat(Tuple{X,Y,V})) = [t]
# annotations(v::AVec{PlotText}) = v
# annotations(v::AVec) = map(PlotText, v)
# annotations(anns) = error("Expecting a tuple (or vector of tuples) for annotations: ",
# "(x, y, annotation)\n got: $(typeof(anns))")
# function annotations(plt::Plot, anns)
# anns = annotations(anns)
# # if we just have a list of PlotText objects, then create (x,y,text) tuples
# if typeof(anns) <: AVec{PlotText}
# x, y = plt[plt.n]
# anns = Tuple{Float64,Float64,PlotText}[(x[i], y[i], t) for (i,t) in enumerate(anns)]
# end
# anns
# end
# function _add_annotations(plt::Plot, d::KW)
# anns = annotations(get(d, :annotation, nothing))
# if !isempty(anns)
#
# # if we just have a list of PlotText objects, then create (x,y,text) tuples
# if typeof(anns) <: AVec{PlotText}
# x, y = plt[plt.n]
# anns = Tuple{Float64,Float64,PlotText}[(x[i], y[i], t) for (i,t) in enumerate(anns)]
# end
#
# _add_annotations(plt, anns)
# end
# end
# --------------------------------------------------------------------

View File

@ -1,7 +1,15 @@
function Subplot{T<:AbstractBackend}(::T; parent = RootLayout())
Subplot{T}(parent, defaultbox, defaultbox, KW(), nothing, nothing)
Subplot{T}(
parent,
(20mm, 5mm, 2mm, 10mm),
defaultbox,
defaultbox,
KW(),
nothing,
nothing
)
end
plotarea!(sp::Subplot, bbox::BoundingBox) = (sp.plotarea = bbox)
@ -11,6 +19,10 @@ Base.size(sp::Subplot) = (1,1)
Base.length(sp::Subplot) = 1
Base.getindex(sp::Subplot, r::Int, c::Int) = sp
leftpad(sp::Subplot) = sp.minpad[1]
toppad(sp::Subplot) = sp.minpad[2]
rightpad(sp::Subplot) = sp.minpad[3]
bottompad(sp::Subplot) = sp.minpad[4]
get_subplot(plt::Plot, sp::Subplot) = sp
get_subplot(plt::Plot, i::Integer) = plt.subplots[i]

View File

@ -32,6 +32,7 @@ end
# a single subplot
type Subplot{T<:AbstractBackend} <: AbstractLayout
parent::AbstractLayout
minpad::Tuple # leftpad, toppad, rightpad, bottompad
bbox::BoundingBox # the canvas area which is available to this subplot
plotarea::BoundingBox # the part where the data goes
attr::KW # args specific to this subplot

View File

@ -481,14 +481,44 @@ function getxyz(plt::Plot, i::Integer)
end
function setxy!{X,Y}(plt::Plot, xy::Tuple{X,Y}, i::Integer)
d = plt.series_list[i].d
d[:x], d[:y] = xy
series = plt.series_list[i]
series.d[:x], series.d[:y] = xy
_series_updated(plt, series)
end
function setxyz!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer)
d = plt.series_list[i].d
d[:x], d[:y], d[:z] = xyz
series = plt.series_list[i]
series.d[:x], series.d[:y], series.d[:z] = xyz
_series_updated(plt, series)
end
#
#
# function setxy!{X,Y}(plt::Plot{PyPlotBackend}, xy::Tuple{X,Y}, i::Integer)
# series = plt.series_list[i]
# d = series.d
# d[:x], d[:y] = xy
# for handle in d[:serieshandle]
# try
# handle[:set_data](xy...)
# catch
# handle[:set_offsets](hcat(xy...))
# end
# end
# update_limits!(d[:subplot], series, (:x,:y))
# plt
# end
#
#
# function setxyz!{X,Y,Z}(plt::Plot{PyPlotBackend}, xyz::Tuple{X,Y,Z}, i::Integer)
# series = plt.series_list[i]
# d = series.d
# d[:x], d[:y], d[:z] = xyz
# for handle in d[:serieshandle]
# handle[:set_data](d[:x], d[:y])
# handle[:set_3d_properties](d[:z])
# end
# update_limits!(d[:subplot], series, (:x,:y,:z))
# plt
# end
# -------------------------------------------------------
# indexing notation