diff --git a/src/args.jl b/src/args.jl index ca649a1a..b655863e 100644 --- a/src/args.jl +++ b/src/args.jl @@ -156,7 +156,7 @@ _seriesDefaults[:weights] = nothing # optional weights for histograms _seriesDefaults[:contours] = false # add contours to 3d surface and wireframe plots _seriesDefaults[:match_dimensions] = false # do rows match x (true) or y (false) for heatmap/image/spy? see issue 196 # this ONLY effects whether or not the z-matrix is transposed for a heatmap display! -_seriesDefaults[:subplot_index] = :auto +_seriesDefaults[:subplot] = :auto const _plotDefaults = KW() @@ -721,7 +721,7 @@ end function warnOnUnsupportedArgs(pkg::AbstractBackend, d::KW) for k in sortedkeys(d) if (!(k in supportedArgs(pkg)) - && k != :subplot + # && k != :subplot && d[k] != default(k)) warn("Keyword argument $k not supported with $pkg. Choose from: $(supportedArgs(pkg))") end diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 106a423f..3370e3e0 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -234,13 +234,13 @@ renderer(fig) = canvas(fig)[:get_renderer]() drawfig(fig) = fig[:draw](renderer(fig)) drawax(ax) = ax[:draw](renderer(ax[:get_figure]())) -bbox(obj) = obj[:get_window_extent](renderer(obj[:get_figure]())) -pos(obj) = obj[:get_position]() +# bbox(obj) = obj[:get_window_extent](renderer(obj[:get_figure]())) +# pos(obj) = obj[:get_position]() -# merge a list of bounding boxes together to become the area that surrounds them all -bbox_union(bboxes) = pytransforms.Bbox[:union](bboxes) +# # merge a list of bounding boxes together to become the area that surrounds them all +# bbox_union(bboxes) = pytransforms.Bbox[:union](bboxes) -function bbox_pct(obj) +function py_bbox_pct(obj) pybbox_pixels = obj[:get_window_extent]() fig = obj[:get_figure]() pybbox_pct = pybbox_pixels[:inverse_transformed](fig[:transFigure]) @@ -250,7 +250,7 @@ end # bbox_from_pyplot(obj) = -function bbox_ticks(ax, letter) +function py_bbox_ticks(ax, letter) # fig = ax[:get_figure]() # @show fig labels = ax[symbol("get_"*letter*"ticklabels")]() @@ -259,42 +259,63 @@ function bbox_ticks(ax, letter) bbox_union = BoundingBox() for lab in labels # @show lab,lab[:get_text]() - bbox = bbox_pct(lab) + bbox = py_bbox_pct(lab) bbox_union = bbox_union + bbox # @show bbox_union end bbox_union end -function bbox_axislabel(ax, letter) - pyaxis_label = ax[symbol("get_"*letter*"axis")]() - bbox_pct(pyaxis_label) +function py_bbox_axislabel(ax, letter) + pyaxis_label = ax[symbol("get_"*letter*"axis")]()[:label] + py_bbox_pct(pyaxis_label) end # get a bounding box for the whole axis -function bbox_axis(ax, letter) - bbox_ticks(ax, letter) + bbox_axislabel(ax, letter) +function py_bbox_axis(ax, letter) + py_bbox_ticks(ax, letter) + py_bbox_axislabel(ax, letter) end # get a bounding box for the title area -function bbox_title(ax) - bbox_pct(ax[:title]) +function py_bbox_title(ax) + py_bbox_pct(ax[:title]) end -xaxis_height(sp::Subplot{PyPlotBackend}) = height(bbox_axis(sp.o,"x")) -yaxis_width(sp::Subplot{PyPlotBackend}) = width(bbox_axis(sp.o,"y")) -title_height(sp::Subplot{PyPlotBackend}) = height(bbox_title(sp.o)) +xaxis_height(sp::Subplot{PyPlotBackend}) = height(py_bbox_axis(sp.o,"x")) +yaxis_width(sp::Subplot{PyPlotBackend}) = width(py_bbox_axis(sp.o,"y")) +title_height(sp::Subplot{PyPlotBackend}) = height(py_bbox_title(sp.o)) + +# note: this overrides the default version to allow for labels that stick out the sides +# bounding box (relative to canvas) for plot area +# note: we assume the x axis is on the left, and y axis is on the bottom +# TODO: really the padding below should be part of the freespace calc, and we should probably +# cache the plotarea bbox while we're doing that (need to add plotarea field to Subplot) +function plotarea_bbox(sp::Subplot{PyPlotBackend}) + ax = sp.o + plot_bb = py_bbox_pct(ax) + xbb = py_bbox_axis(ax, "x") + ybb = py_bbox_axis(ax, "y") + titbb = py_bbox_title(ax) + items = [xbb, ybb, titbb] + # TODO: add in margin/padding from sp.attr + leftpad = max(0, left(plot_bb) - minimum(map(left, items))) + bottompad = max(0, bottom(plot_bb) - minimum(map(bottom, items))) + rightpad = max(0, maximum(map(right, items)) - right(plot_bb)) + toppad = max(0, maximum(map(top, items)) - top(plot_bb)) + # crop(bbox(sp), BoundingBox(yaxis_width(sp), xaxis_height(sp), 1, 1 - title_height(sp))) + crop(bbox(sp), BoundingBox(leftpad, bottompad, 1 - rightpad, 1 - toppad)) +end # --------------------------------------------------------------------------- # function used_width(sp::Subplot{PyPlotBackend}) # ax = sp.o -# width(bbox_axis(ax,"y")) +# width(py_bbox_axis(ax,"y")) # end # # function used_height(sp::Subplot{PyPlotBackend}) # ax = sp.o -# height(bbox_axis(ax,"x")) + height(bbox_title(ax)) +# height(py_bbox_axis(ax,"x")) + height(py_bbox_title(ax)) # end @@ -309,28 +330,29 @@ function update_position!(sp::Subplot{PyPlotBackend}) ax[:set_position]([f(bb) for f in (left, bottom, width, height)]) end -# --------------------------------------------------------------------------- - -function getAxis(plt::Plot{PyPlotBackend}, subplot::Subplot = plt.subplots[1]) - if subplot.o == nothing - @show subplot - fig = plt.o - @show fig - # if fig == nothing - # fig = - # TODO: actual coords? - # NOTE: might want to use ax[:get_tightbbox](ax[:get_renderer_cache]()) to calc size of guides? - # NOTE: can set subplot location later with ax[:set_position]([left, bottom, width, height]) - # left, bottom, width, height = 0.3, 0.3, 0.5, 0.5 - - # init to the full canvas, then we can set_position later - ax = fig[:add_axes]([0,0,1,1]) - subplot.o = ax +# each backend should set up the subplot here +function _initialize_subplot(plt::Plot{PyPlotBackend}, sp::Subplot{PyPlotBackend}) + fig = plt.o + ax = fig[:add_axes]([0,0,1,1]) + for axis in (:xaxis, :yaxis) + ax[axis][:_autolabelpos] = false end - subplot.o + sp.o = ax end -getLeftAxis(plt::Plot{PyPlotBackend}, subplot::Subplot = plt.subplots[1]) = getAxis(plt, subplot) +# --------------------------------------------------------------------------- + +# these can probably be removed eventually... right now they're just keeping things working before cleanup +# getAxis(plt::Plot{PyPlotBackend}, subplot::Subplot = plt.subplots[1]) = subplot.o + +getAxis(sp::Subplot) = sp.o + +function getAxis(plt::Plot{PyPlotBackend}, series::Series) + sp = get_subplot(plt, get(series.d, :subplot, 1)) + getAxis(sp) +end + +# getLeftAxis(plt::Plot{PyPlotBackend}, subplot::Subplot = plt.subplots[1]) = getAxis(plt, subplot) getfig(o) = o # --------------------------------------------------------------------------- @@ -501,7 +523,7 @@ function _add_series(plt::Plot{PyPlotBackend}, series::Series) fix_xy_lengths!(plt, d) # ax = getAxis(plt, d[:axis]) - ax = getAxis(plt, get(d, :subplot, plt.subplots[1])) + ax = getAxis(plt, series) x, y, z = d[:x], d[:y], d[:z] @show typeof((x,y,z)) xyargs = (st in _3dTypes ? (x,y,z) : (x,y)) @@ -889,42 +911,43 @@ end # ----------------------------------------------------------------- -# given a dimension (:x, :y, or :z), loop over the seriesargs KWs to find the min/max of the underlying data -function minmaxseries(series_list, dimension, axis) - lo, hi = Inf, -Inf - for series in series_list - series.d[:axis] == axis || continue - v = series.d[dimension] - if length(v) > 0 - vlo, vhi = extrema(v) - lo = min(lo, vlo) - hi = max(hi, vhi) - end - end - if lo == hi - hi = if lo == 0 - 1e-6 - else - hi + min(abs(1e-2hi), 1e-6) - end - end - lo, hi -end - -# TODO: this needs to handle one-sided fixed limits -function set_lims!(plt::Plot{PyPlotBackend}, axis::Symbol) - ax = getAxis(plt, axis) - pargs = plt.plotargs - if pargs[:xlims] == :auto - ax[pargs[:polar] ? :set_tlim : :set_xlim](minmaxseries(plt.series_list, :x, axis)...) - end - if pargs[:ylims] == :auto - ax[pargs[:polar] ? :set_rlim : :set_ylim](minmaxseries(plt.series_list, :y, axis)...) - end - if pargs[:zlims] == :auto && haskey(ax, :set_zlim) - ax[:set_zlim](minmaxseries(plt.series_list, :z, axis)...) - end -end +# # given a dimension (:x, :y, or :z), loop over the seriesargs KWs to find the min/max of the underlying data +# function minmaxseries(series_list, dimension, axis) +# lo, hi = Inf, -Inf +# for series in series_list +# series.d[:axis] == axis || continue +# v = series.d[dimension] +# if length(v) > 0 +# vlo, vhi = extrema(v) +# lo = min(lo, vlo) +# hi = max(hi, vhi) +# end +# end +# if lo == hi +# hi = if lo == 0 +# 1e-6 +# else +# hi + min(abs(1e-2hi), 1e-6) +# end +# end +# lo, hi +# end +# +# # TODO: this needs to handle one-sided fixed limits +# # TODO: this should be handled within the Axis type +# function set_lims!(plt::Plot{PyPlotBackend}, axis::Symbol) +# ax = getAxis(plt, axis) +# pargs = plt.plotargs +# if pargs[:xlims] == :auto +# ax[pargs[:polar] ? :set_tlim : :set_xlim](minmaxseries(plt.series_list, :x, axis)...) +# end +# if pargs[:ylims] == :auto +# ax[pargs[:polar] ? :set_rlim : :set_ylim](minmaxseries(plt.series_list, :y, axis)...) +# end +# if pargs[:zlims] == :auto && haskey(ax, :set_zlim) +# ax[:set_zlim](minmaxseries(plt.series_list, :z, axis)...) +# end +# end # -------------------------------------------------------------------------- @@ -941,7 +964,7 @@ function setxy!{X,Y}(plt::Plot{PyPlotBackend}, xy::Tuple{X,Y}, i::Integer) handle[:set_offsets](hcat(xy...)) end end - set_lims!(plt, d[:axis]) + # set_lims!(plt, plt.series_list[i]) plt end @@ -953,7 +976,7 @@ function setxyz!{X,Y,Z}(plt::Plot{PyPlotBackend}, xyz::Tuple{X,Y,Z}, i::Integer) handle[:set_data](d[:x], d[:y]) handle[:set_3d_properties](d[:z]) end - set_lims!(plt, d[:axis]) + # set_lims!(plt, plt.series_list[i]) plt end @@ -1032,115 +1055,120 @@ end function _update_plot(plt::Plot{PyPlotBackend}, d::KW) # @show d - figorax = plt.o + # figorax = plt.o # ax = getLeftAxis(figorax) - ax = getAxis(plt, plt.subplots[1]) - # ticksz = get(d, :tickfont, plt.plotargs[:tickfont]).pointsize - guidesz = get(d, :guidefont, plt.plotargs[:guidefont]).pointsize + for sp in plt.subplots + ax = getAxis(sp) + # ticksz = get(d, :tickfont, plt.plotargs[:tickfont]).pointsize + guidesz = get(d, :guidefont, plt.plotargs[:guidefont]).pointsize - # title - haskey(d, :title) && ax[:set_title](d[:title]) - ax[:title][:set_fontsize](guidesz) + # title + haskey(d, :title) && ax[:set_title](d[:title]) + ax[:title][:set_fontsize](guidesz) - axes = [ax] - # # handle right y axis - # axes = [getLeftAxis(figorax)] - # if usingRightAxis(plt) - # push!(axes, getRightAxis(figorax)) - # if get(d, :yrightlabel, "") != "" - # rightax = getRightAxis(figorax) - # rightax[:set_ylabel](d[:yrightlabel]) - # end - # end + # axes = [ax] + # # handle right y axis + # axes = [getLeftAxis(figorax)] + # if usingRightAxis(plt) + # push!(axes, getRightAxis(figorax)) + # if get(d, :yrightlabel, "") != "" + # rightax = getRightAxis(figorax) + # rightax[:set_ylabel](d[:yrightlabel]) + # end + # end - for letter in ("x", "y", "z") - axissym = symbol(letter*"axis") - axis = plt.plotargs[axissym] - # @show axis - haskey(ax, axissym) || continue - applyPyPlotScale(ax, axis[:scale], letter) - addPyPlotLims(ax, axis[:lims], letter) - addPyPlotTicks(ax, get_ticks(axis), letter) - ax[symbol("set_", letter, "label")](axis[:label]) - if get(axis.d, :flip, false) - ax[symbol("invert_", letter, "axis")]() - end - for tmpax in axes - tmpax[axissym][:label][:set_fontsize](axis[:guidefont].pointsize) - for lab in tmpax[symbol("get_", letter, "ticklabels")]() - lab[:set_fontsize](axis[:tickfont].pointsize) - lab[:set_rotation](axis[:rotation]) - end - if get(d, :grid, false) - fgcolor = getPyPlotColor(plt.plotargs[:foreground_color_grid]) - tmpax[axissym][:grid](true, color = fgcolor) - tmpax[:set_axisbelow](true) + for letter in ("x", "y", "z") + axissym = symbol(letter*"axis") + axis = plt.plotargs[axissym] + # @show axis + haskey(ax, axissym) || continue + applyPyPlotScale(ax, axis[:scale], letter) + addPyPlotLims(ax, axis[:lims], letter) + addPyPlotTicks(ax, get_ticks(axis), letter) + ax[symbol("set_", letter, "label")](axis[:label]) + if get(axis.d, :flip, false) + ax[symbol("invert_", letter, "axis")]() end + # for tmpax in axes + tmpax = ax + tmpax[axissym][:label][:set_fontsize](axis[:guidefont].pointsize) + for lab in tmpax[symbol("get_", letter, "ticklabels")]() + lab[:set_fontsize](axis[:tickfont].pointsize) + lab[:set_rotation](axis[:rotation]) + end + if get(d, :grid, false) + fgcolor = getPyPlotColor(plt.plotargs[:foreground_color_grid]) + tmpax[axissym][:grid](true, color = fgcolor) + tmpax[:set_axisbelow](true) + end + # end + # @show "" end - # @show "" - end - # # handle each axis in turn - # for letter in ("x", "y", "z") - # axis, scale, lims, ticks, flip, lab, rotation = - # axis_symbols(letter, "axis", "scale", "lims", "ticks", "flip", "label", "rotation") - # haskey(ax, axis) || continue - # haskey(d, scale) && applyPyPlotScale(ax, d[scale], letter) - # haskey(d, lims) && addPyPlotLims(ax, d[lims], letter) - # haskey(d, ticks) && addPyPlotTicks(ax, d[ticks], letter) - # haskey(d, lab) && ax[symbol("set_", letter, "label")](d[lab]) - # if get(d, flip, false) - # ax[symbol("invert_", letter, "axis")]() - # end - # for tmpax in axes - # tmpax[axis][:label][:set_fontsize](guidesz) - # for lab in tmpax[symbol("get_", letter, "ticklabels")]() - # lab[:set_fontsize](ticksz) - # haskey(d, rotation) && lab[:set_rotation](d[rotation]) - # end - # if get(d, :grid, false) - # fgcolor = getPyPlotColor(plt.plotargs[:foreground_color_grid]) - # tmpax[axis][:grid](true, color = fgcolor) - # tmpax[:set_axisbelow](true) - # end - # end - # end + # # handle each axis in turn + # for letter in ("x", "y", "z") + # axis, scale, lims, ticks, flip, lab, rotation = + # axis_symbols(letter, "axis", "scale", "lims", "ticks", "flip", "label", "rotation") + # haskey(ax, axis) || continue + # haskey(d, scale) && applyPyPlotScale(ax, d[scale], letter) + # haskey(d, lims) && addPyPlotLims(ax, d[lims], letter) + # haskey(d, ticks) && addPyPlotTicks(ax, d[ticks], letter) + # haskey(d, lab) && ax[symbol("set_", letter, "label")](d[lab]) + # if get(d, flip, false) + # ax[symbol("invert_", letter, "axis")]() + # end + # for tmpax in axes + # tmpax[axis][:label][:set_fontsize](guidesz) + # for lab in tmpax[symbol("get_", letter, "ticklabels")]() + # lab[:set_fontsize](ticksz) + # haskey(d, rotation) && lab[:set_rotation](d[rotation]) + # end + # if get(d, :grid, false) + # fgcolor = getPyPlotColor(plt.plotargs[:foreground_color_grid]) + # tmpax[axis][:grid](true, color = fgcolor) + # tmpax[:set_axisbelow](true) + # end + # end + # end - # do we want to change the aspect ratio? - aratio = get(d, :aspect_ratio, :none) - if aratio != :none - ax[:set_aspect](isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C") + # do we want to change the aspect ratio? + aratio = get(d, :aspect_ratio, :none) + if aratio != :none + ax[:set_aspect](isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C") + end end end # ----------------------------------------------------------------- -function createPyPlotAnnotationObject(plt::Plot{PyPlotBackend}, x, y, val::@compat(AbstractString)) - ax = getLeftAxis(plt) - ax[:annotate](val, xy = (x,y)) -end +# TODO: these should apply to a Subplot, NOT a Plot - -function createPyPlotAnnotationObject(plt::Plot{PyPlotBackend}, x, y, val::PlotText) - ax = getLeftAxis(plt) - ax[:annotate](val.str, - xy = (x,y), - family = val.font.family, - color = getPyPlotColor(val.font.color), - horizontalalignment = val.font.halign == :hcenter ? "center" : string(val.font.halign), - verticalalignment = val.font.valign == :vcenter ? "center" : string(val.font.valign), - rotation = val.font.rotation * 180 / π, - size = val.font.pointsize - ) -end - -function _add_annotations{X,Y,V}(plt::Plot{PyPlotBackend}, anns::AVec{@compat(Tuple{X,Y,V})}) - for ann in anns - createPyPlotAnnotationObject(plt, ann...) - end -end +# function createPyPlotAnnotationObject(plt::Plot{PyPlotBackend}, x, y, val::@compat(AbstractString)) +# ax = getLeftAxis(plt) +# ax[:annotate](val, xy = (x,y)) +# end +# +# +# function createPyPlotAnnotationObject(plt::Plot{PyPlotBackend}, x, y, val::PlotText) +# ax = getLeftAxis(plt) +# ax[:annotate](val.str, +# xy = (x,y), +# family = val.font.family, +# color = getPyPlotColor(val.font.color), +# horizontalalignment = val.font.halign == :hcenter ? "center" : string(val.font.halign), +# verticalalignment = val.font.valign == :vcenter ? "center" : string(val.font.valign), +# rotation = val.font.rotation * 180 / π, +# size = val.font.pointsize +# ) +# end +# +# function _add_annotations{X,Y,V}(plt::Plot{PyPlotBackend}, anns::AVec{@compat(Tuple{X,Y,V})}) +# for ann in anns +# createPyPlotAnnotationObject(plt, ann...) +# end +# end # ----------------------------------------------------------------- @@ -1271,9 +1299,12 @@ end # ----------------------------------------------------------------- function finalizePlot(plt::Plot{PyPlotBackend}) - ax = getLeftAxis(plt) - addPyPlotLegend(plt, ax) - updateAxisColors(ax, plt.plotargs) + for sp in plt.subplots + # ax = getLeftAxis(plt) + ax = getAxis(sp) + addPyPlotLegend(plt, ax) + updateAxisColors(ax, plt.plotargs) + end drawfig(plt.o) update_bboxes!(plt.layout) update_position!(plt.layout) diff --git a/src/plot.jl b/src/plot.jl index 8bd2d2f2..0fa292d7 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -47,7 +47,6 @@ function plot(args...; kw...) d = KW(kw) preprocessArgs!(d) - layout, subplots, spmap = build_layout(pop!(d, :layout, :auto)) # subplots = Subplot[layout] # TODO: build full list # smap = SubplotMap(1 => layout) # TODO: actually build a map @@ -55,9 +54,15 @@ function plot(args...; kw...) plotargs = merge(d, getPlotArgs(pkg, d, 1)) # plt = _create_plot(pkg, plotargs) # create a new, blank plot - plt = Plot(nothing, pkg, 0, plotargs, Series[], subplots, spmap, layout) + # plt = Plot(nothing, pkg, 0, plotargs, Series[]) #, subplots, spmap, layout) + plt = Plot(plotargs) plt.o = _create_backend_figure(plt) + plt.layout, plt.subplots, plt.spmap = build_layout(pop!(d, :layout, :auto)) + for sp in plt.subplots + _initialize_subplot(plt, sp) + end + # now update the plot _plot!(plt, d, args...) end diff --git a/src/subplots.jl b/src/subplots.jl index 642fbaae..4042ecc1 100644 --- a/src/subplots.jl +++ b/src/subplots.jl @@ -58,6 +58,9 @@ used_size(layout::AbstractLayout) = (used_width(layout), used_height(layout)) # # end +update_position!(layout::AbstractLayout) = nothing +update_bboxes!(layout::AbstractLayout) = nothing + # ---------------------------------------------------------------------- Base.size(layout::EmptyLayout) = (0,0) @@ -67,7 +70,6 @@ Base.getindex(layout::EmptyLayout, r::Int, c::Int) = nothing used_width(layout::EmptyLayout) = 0.0 used_height(layout::EmptyLayout) = 0.0 -update_position!(layout::EmptyLayout) = nothing # ---------------------------------------------------------------------- @@ -118,7 +120,7 @@ function used_width(layout::GridLayout) w = 0.0 nr,nc = size(layout) for c=1:nc - w += maximum([used_width(layout(r,c)) for r=1:nr]) + w += maximum([used_width(layout[r,c]) for r=1:nr]) end w end @@ -127,7 +129,7 @@ function used_height(layout::GridLayout) h = 0.0 nr,nc = size(layout) for r=1:nr - h += maximum([used_height(layout(r,c)) for c=1:nc]) + h += maximum([used_height(layout[r,c]) for c=1:nc]) end h end @@ -142,8 +144,8 @@ function update_bboxes!(layout::GridLayout) #, parent_bbox::BoundingBox = Boundi # initialize the free space (per child!) nr, nc = size(layout) freew, freeh = free_size(layout) - freew /= nc - freeh /= nr + freew /= sum(layout.widths) + freeh /= sum(layout.heights) # TODO: this should really track used/free space for each row/column so that we can align plot areas properly @@ -152,7 +154,11 @@ function update_bboxes!(layout::GridLayout) #, parent_bbox::BoundingBox = Boundi # compute the child's bounding box relative to the parent child = layout[r,c] usedw, usedh = used_size(child) - child_bbox = BoundingBox(l, b, l + usedw + freew, b + usedh + freeh) + child_bbox = BoundingBox( + l, b, + l + usedw + freew * layout.widths[c], + b + usedh + freeh * layout.heights[r] + ) # then compute the bounding box relative to the canvas, and cache it in the child object bbox!(child, crop(bbox(layout), child_bbox)) @@ -167,7 +173,7 @@ end # return the top-level layout, a list of subplots, and a SubplotMap function build_layout(s::Symbol) s == :auto || error() # TODO: handle anything else - layout = GridLayout(1, 2) + layout = GridLayout(1, 2) #TODO this need to go nr, nc = size(layout) subplots = Subplot[] spmap = SubplotMap() @@ -181,6 +187,11 @@ function build_layout(s::Symbol) end # ---------------------------------------------------------------------- + +get_subplot(plt::Plot, sp::Subplot) = sp +get_subplot(plt::Plot, i::Integer) = plt.subplots[i] +get_subplot(plt::Plot, k) = plt.spmap[k] + # ---------------------------------------------------------------------- # ---------------------------------------------------------------------- diff --git a/src/types.jl b/src/types.jl index 571244da..f9bd5ea5 100644 --- a/src/types.jl +++ b/src/types.jl @@ -56,7 +56,7 @@ type EmptyLayout <: AbstractLayout parent::AbstractLayout bbox::BoundingBox end -EmptyLayout(parent) = EmptyLayout(parent, BoundingBox(0,0,1,1)) +EmptyLayout(parent = RootLayout()) = EmptyLayout(parent, BoundingBox(0,0,1,1)) # this is the parent of the top-level layout immutable RootLayout <: AbstractLayout @@ -123,17 +123,20 @@ type Series end type Plot{T<:AbstractBackend} <: AbstractPlot{T} - o # the backend's plot object backend::T # the backend type n::Int # number of series plotargs::KW # arguments for the whole plot - # seriesargs::Vector{KW} # arguments for each series series_list::Vector{Series} # arguments for each series + o # the backend's plot object subplots::Vector{Subplot} - subplot_map::SubplotMap # provide any label as a map to a subplot + spmap::SubplotMap # provide any label as a map to a subplot layout::AbstractLayout end +function Plot(plotargs::KW) + Plot(backend(), 0, plotargs, Series[], nothing, Subplot[], SubplotMap(), EmptyLayout()) +end + # ----------------------------------------------------------- # Subplot # -----------------------------------------------------------