inset_subplots; GR log axes fix

This commit is contained in:
Thomas Breloff 2016-06-13 12:27:48 -04:00
parent 3b33b054d3
commit 266d2efde5
7 changed files with 67 additions and 5 deletions

View File

@ -19,6 +19,8 @@ export
GridLayout, GridLayout,
grid, grid,
EmptyLayout, EmptyLayout,
bbox,
plotarea,
@layout, @layout,
AVec, AVec,
AMat, AMat,

View File

@ -60,6 +60,7 @@ const _arg_desc = KW(
:link => "Symbol. How/whether to link axis limits between subplots. Values: `:none`, `:x` (x axes are linked by columns), `:y` (y axes are linked by rows), `:both` (x and y are linked), `:all` (every subplot is linked together regardless of layout position).", :link => "Symbol. How/whether to link axis limits between subplots. Values: `:none`, `:x` (x axes are linked by columns), `:y` (y axes are linked by rows), `:both` (x and y are linked), `:all` (every subplot is linked together regardless of layout position).",
:overwrite_figure => "Bool. Should we reuse the same GUI window/figure when plotting (true) or open a new one (false).", :overwrite_figure => "Bool. Should we reuse the same GUI window/figure when plotting (true) or open a new one (false).",
:html_output_format => "Symbol. When writing html output, what is the format? `:png` and `:svg` are currently supported.", :html_output_format => "Symbol. When writing html output, what is the format? `:png` and `:svg` are currently supported.",
:inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots",
# subplot args # subplot args
:title => "String. Subplot title.", :title => "String. Subplot title.",

View File

@ -198,6 +198,8 @@ const _plot_defaults = KW(
:link => :none, :link => :none,
:overwrite_figure => true, :overwrite_figure => true,
:html_output_format => :auto, :html_output_format => :auto,
:inset_subplots => nothing, # optionally pass a vector of (parent,bbox) tuples which are
# the parent layout and the relative bounding box of inset subplots
) )
@ -256,6 +258,7 @@ const _suppress_warnings = Set{Symbol}([
:plot_object, :plot_object,
:primary, :primary,
:smooth, :smooth,
:relative_bbox,
]) ])
# add defaults for the letter versions # add defaults for the letter versions

View File

@ -576,8 +576,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
x1, x2 = xaxis[:flip] ? (xmax,xmin) : (xmin,xmax) x1, x2 = xaxis[:flip] ? (xmax,xmin) : (xmin,xmax)
y1, y2 = yaxis[:flip] ? (ymax,ymin) : (ymin,ymax) y1, y2 = yaxis[:flip] ? (ymax,ymin) : (ymin,ymax)
GR.axes(xtick, ytick, x1, y1, majorx, majory, ticksize) GR.axes(xtick, ytick, x1, y1, 1, 1, ticksize)
GR.axes(xtick, ytick, x2, y2, -majorx, -majory, -ticksize) GR.axes(xtick, ytick, x2, y2, -1, -1, -ticksize)
end end
# end # end

View File

@ -101,6 +101,9 @@ end
Base.show(io::IO, layout::AbstractLayout) = print(io, "$(typeof(layout))$(size(layout))") Base.show(io::IO, layout::AbstractLayout) = print(io, "$(typeof(layout))$(size(layout))")
# create a new bbox
bbox(left, top, w, h) = BoundingBox(left, top, w, h)
# this is the available area for drawing everything in this layout... as percentages of total canvas # this is the available area for drawing everything in this layout... as percentages of total canvas
bbox(layout::AbstractLayout) = layout.bbox bbox(layout::AbstractLayout) = layout.bbox
bbox!(layout::AbstractLayout, bb::BoundingBox) = (layout.bbox = bb) bbox!(layout::AbstractLayout, bb::BoundingBox) = (layout.bbox = bb)
@ -116,8 +119,12 @@ parent_bbox(layout::AbstractLayout) = bbox(parent(layout))
update_position!(layout::AbstractLayout) = nothing update_position!(layout::AbstractLayout) = nothing
update_child_bboxes!(layout::AbstractLayout, minimum_perimeter = [0mm,0mm,0mm,0mm]) = nothing update_child_bboxes!(layout::AbstractLayout, minimum_perimeter = [0mm,0mm,0mm,0mm]) = nothing
width(layout::AbstractLayout) = width(layout.bbox) left(layout::AbstractLayout) = left(bbox(layout))
height(layout::AbstractLayout) = height(layout.bbox) top(layout::AbstractLayout) = top(bbox(layout))
right(layout::AbstractLayout) = right(bbox(layout))
bottom(layout::AbstractLayout) = bottom(bbox(layout))
width(layout::AbstractLayout) = width(bbox(layout))
height(layout::AbstractLayout) = height(bbox(layout))
plotarea(layout::AbstractLayout) = defaultbox plotarea(layout::AbstractLayout) = defaultbox
plotarea!(layout::AbstractLayout, bbox::BoundingBox) = nothing plotarea!(layout::AbstractLayout, bbox::BoundingBox) = nothing
@ -335,6 +342,26 @@ function update_child_bboxes!(layout::GridLayout, minimum_perimeter = [0mm,0mm,0
end end
end end
function update_inset_bboxes!(plt::Plot)
for sp in plt.inset_subplots
relative_bbox = sp[:relative_bbox]
# TODO: need to handle percentages... right now only AbsoluteLength works
bb = bbox!(sp, bbox(
left(sp.parent) + left(relative_bbox),
top(sp.parent) + top(relative_bbox),
width(relative_bbox),
height(relative_bbox)
))
plotarea!(sp, bbox(
left(bb) + leftpad(sp),
top(bb) + toppad(sp),
width(bb) - leftpad(sp) - rightpad(sp),
height(bb) - toppad(sp) - bottompad(sp)
))
end
end
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------

View File

@ -350,6 +350,27 @@ function _plot!(plt::Plot, d::KW, args...)
sp.attr[:subplot_index] = idx sp.attr[:subplot_index] = idx
end end
# handle inset subplots
insets = plt[:inset_subplots]
if insets != nothing
for (parent, bb) in insets
P = typeof(parent)
if P <: Integer
parent = plt.subplots[parent]
elseif P == Symbol
parent = plt.spmap[parent]
else
parent = plt.layout
end
sp = Subplot(backend(), parent=parent)
sp.plt = plt
sp.attr[:relative_bbox] = bb
push!(plt.subplots, sp)
sp.attr[:subplot_index] = length(plt.subplots)
push!(plt.inset_subplots, sp)
end
end
plt.init = true plt.init = true
end end
@ -440,10 +461,16 @@ function prepare_output(plt::Plot)
# One pass down and back up the tree to compute the minimum padding # One pass down and back up the tree to compute the minimum padding
# of the children on the perimeter. This is an backend callback. # of the children on the perimeter. This is an backend callback.
_update_min_padding!(plt.layout) _update_min_padding!(plt.layout)
for sp in plt.inset_subplots
_update_min_padding!(sp)
end
# now another pass down, to update the bounding boxes # now another pass down, to update the bounding boxes
update_child_bboxes!(plt.layout) update_child_bboxes!(plt.layout)
# update those bounding boxes of inset subplots
update_inset_bboxes!(plt)
# the backend callback, to reposition subplots, etc # the backend callback, to reposition subplots, etc
_update_plot_object(plt) _update_plot_object(plt)
end end

View File

@ -73,12 +73,14 @@ type Plot{T<:AbstractBackend} <: AbstractPlot{T}
subplots::Vector{Subplot} subplots::Vector{Subplot}
spmap::SubplotMap # provide any label as a map to a subplot spmap::SubplotMap # provide any label as a map to a subplot
layout::AbstractLayout layout::AbstractLayout
inset_subplots::Vector{Subplot} # list of inset subplots
init::Bool init::Bool
end end
function Plot() function Plot()
Plot(backend(), 0, KW(), KW(), Series[], nothing, Plot(backend(), 0, KW(), KW(), Series[], nothing,
Subplot[], SubplotMap(), EmptyLayout(), false) Subplot[], SubplotMap(), EmptyLayout(),
Subplot[], false)
end end
# TODO: make a decision... should plt[1] return the first subplot or the first series?? # TODO: make a decision... should plt[1] return the first subplot or the first series??