smarter cleanup of dicts; layout fixes: split out update_min_padding and added minimum_perimeter logic; check for nonempty axes when linking; add subplot processing and linking when combining plots
This commit is contained in:
parent
d7098f77c2
commit
8007d0dd6a
80
src/args.jl
80
src/args.jl
@ -896,78 +896,75 @@ end
|
|||||||
|
|
||||||
# update attr from an input dictionary
|
# update attr from an input dictionary
|
||||||
function _update_plot_args(plt::Plot, d_in::KW)
|
function _update_plot_args(plt::Plot, d_in::KW)
|
||||||
pargs = plt.attr
|
|
||||||
for (k,v) in _plot_defaults
|
for (k,v) in _plot_defaults
|
||||||
slice_arg!(d_in, pargs, k, v)
|
slice_arg!(d_in, plt.attr, k, v)
|
||||||
end
|
end
|
||||||
|
|
||||||
# handle colors
|
# handle colors
|
||||||
bg = convertColor(pargs[:background_color])
|
bg = convertColor(plt.attr[:background_color])
|
||||||
fg = pargs[:foreground_color]
|
fg = plt.attr[:foreground_color]
|
||||||
if fg == :auto
|
if fg == :auto
|
||||||
fg = isdark(bg) ? colorant"white" : colorant"black"
|
fg = isdark(bg) ? colorant"white" : colorant"black"
|
||||||
end
|
end
|
||||||
pargs[:background_color] = bg
|
plt.attr[:background_color] = bg
|
||||||
pargs[:foreground_color] = convertColor(fg)
|
plt.attr[:foreground_color] = convertColor(fg)
|
||||||
# color_or_match!(pargs, :background_color_outside, bg)
|
# color_or_match!(plt.attr, :background_color_outside, bg)
|
||||||
color_or_nothing!(pargs, :background_color_outside)
|
color_or_nothing!(plt.attr, :background_color_outside)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# update a subplots args and axes
|
# update a subplots args and axes
|
||||||
function _update_subplot_args(plt::Plot, sp::Subplot, d_in::KW, subplot_index::Integer; remove_pair = true)
|
function _update_subplot_args(plt::Plot, sp::Subplot, d_in::KW, subplot_index::Integer; remove_pair = true)
|
||||||
pargs = plt.attr
|
|
||||||
spargs = sp.attr
|
|
||||||
anns = pop!(sp.attr, :annotations, [])
|
anns = pop!(sp.attr, :annotations, [])
|
||||||
|
|
||||||
# grab those args which apply to this subplot
|
# grab those args which apply to this subplot
|
||||||
for (k,v) in _subplot_defaults
|
for (k,v) in _subplot_defaults
|
||||||
slice_arg!(d_in, spargs, k, v, subplot_index, remove_pair = remove_pair)
|
slice_arg!(d_in, sp.attr, k, v, subplot_index, remove_pair = remove_pair)
|
||||||
end
|
end
|
||||||
|
|
||||||
# extend annotations
|
# extend annotations
|
||||||
sp.attr[:annotations] = vcat(anns, sp[:annotations])
|
sp.attr[:annotations] = vcat(anns, sp[:annotations])
|
||||||
|
|
||||||
# handle legend/colorbar
|
# handle legend/colorbar
|
||||||
spargs[:legend] = convertLegendValue(spargs[:legend])
|
sp.attr[:legend] = convertLegendValue(sp.attr[:legend])
|
||||||
spargs[:colorbar] = convertLegendValue(spargs[:colorbar])
|
sp.attr[:colorbar] = convertLegendValue(sp.attr[:colorbar])
|
||||||
if spargs[:colorbar] == :legend
|
if sp.attr[:colorbar] == :legend
|
||||||
spargs[:colorbar] = spargs[:legend]
|
sp.attr[:colorbar] = sp.attr[:legend]
|
||||||
end
|
end
|
||||||
|
|
||||||
# background colors
|
# background colors
|
||||||
# bg = color_or_match!(spargs, :background_color_subplot, pargs[:background_color])
|
# bg = color_or_match!(sp.attr, :background_color_subplot, plt.attr[:background_color])
|
||||||
color_or_nothing!(spargs, :background_color_subplot)
|
color_or_nothing!(sp.attr, :background_color_subplot)
|
||||||
bg = sp[:background_color_subplot]
|
bg = convertColor(sp[:background_color_subplot])
|
||||||
spargs[:color_palette] = get_color_palette(spargs[:color_palette], bg, 30)
|
sp.attr[:color_palette] = get_color_palette(sp.attr[:color_palette], bg, 30)
|
||||||
# color_or_match!(spargs, :background_color_legend, bg)
|
# color_or_match!(sp.attr, :background_color_legend, bg)
|
||||||
color_or_nothing!(spargs, :background_color_legend)
|
color_or_nothing!(sp.attr, :background_color_legend)
|
||||||
# color_or_match!(spargs, :background_color_inside, bg)
|
# color_or_match!(sp.attr, :background_color_inside, bg)
|
||||||
color_or_nothing!(spargs, :background_color_inside)
|
color_or_nothing!(sp.attr, :background_color_inside)
|
||||||
|
|
||||||
# foreground colors
|
# foreground colors
|
||||||
# fg = color_or_match!(spargs, :foreground_color_subplot, pargs[:foreground_color])
|
# fg = color_or_match!(sp.attr, :foreground_color_subplot, plt.attr[:foreground_color])
|
||||||
color_or_nothing!(spargs, :foreground_color_subplot)
|
color_or_nothing!(sp.attr, :foreground_color_subplot)
|
||||||
# color_or_match!(spargs, :foreground_color_legend, fg)
|
# color_or_match!(sp.attr, :foreground_color_legend, fg)
|
||||||
color_or_nothing!(spargs, :foreground_color_legend)
|
color_or_nothing!(sp.attr, :foreground_color_legend)
|
||||||
# color_or_match!(spargs, :foreground_color_grid, fg)
|
# color_or_match!(sp.attr, :foreground_color_grid, fg)
|
||||||
color_or_nothing!(spargs, :foreground_color_grid)
|
color_or_nothing!(sp.attr, :foreground_color_grid)
|
||||||
# color_or_match!(spargs, :foreground_color_title, fg)
|
# color_or_match!(sp.attr, :foreground_color_title, fg)
|
||||||
color_or_nothing!(spargs, :foreground_color_title)
|
color_or_nothing!(sp.attr, :foreground_color_title)
|
||||||
|
|
||||||
# for k in (:left_margin, :top_margin, :right_margin, :bottom_margin)
|
# for k in (:left_margin, :top_margin, :right_margin, :bottom_margin)
|
||||||
# if spargs[k] == :match
|
# if sp.attr[k] == :match
|
||||||
# spargs[k] = spargs[:margin]
|
# sp.attr[k] = sp.attr[:margin]
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
|
|
||||||
for letter in (:x, :y, :z)
|
for letter in (:x, :y, :z)
|
||||||
# get (maybe initialize) the axis
|
# get (maybe initialize) the axis
|
||||||
axissym = Symbol(letter, :axis)
|
axissym = Symbol(letter, :axis)
|
||||||
axis = if haskey(spargs, axissym)
|
axis = if haskey(sp.attr, axissym)
|
||||||
spargs[axissym]
|
sp.attr[axissym]
|
||||||
else
|
else
|
||||||
spargs[axissym] = Axis(sp, letter)
|
sp.attr[axissym] = Axis(sp, letter)
|
||||||
end
|
end
|
||||||
|
|
||||||
# grab magic args (for example `xaxis = (:flip, :log)`)
|
# grab magic args (for example `xaxis = (:flip, :log)`)
|
||||||
@ -987,7 +984,8 @@ function _update_subplot_args(plt::Plot, sp::Subplot, d_in::KW, subplot_index::I
|
|||||||
# then get those args that were passed with a leading letter: `xlabel = "X"`
|
# then get those args that were passed with a leading letter: `xlabel = "X"`
|
||||||
lk = Symbol(letter, k)
|
lk = Symbol(letter, k)
|
||||||
if haskey(d_in, lk)
|
if haskey(d_in, lk)
|
||||||
kw[k] = slice_arg(pop!(d_in, lk), subplot_index)
|
# kw[k] = slice_arg(pop!(d_in, lk), subplot_index)
|
||||||
|
kw[k] = slice_arg(d_in[lk], subplot_index)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1007,10 +1005,10 @@ function _update_subplot_args(plt::Plot, sp::Subplot, d_in::KW, subplot_index::I
|
|||||||
# TODO: need to handle linking here?
|
# TODO: need to handle linking here?
|
||||||
end
|
end
|
||||||
|
|
||||||
# now we can get rid of the axis keys without a letter
|
# # now we can get rid of the axis keys without a letter
|
||||||
for k in keys(_axis_defaults)
|
# for k in keys(_axis_defaults)
|
||||||
delete!(d_in, k)
|
# delete!(d_in, k)
|
||||||
end
|
# end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -97,19 +97,12 @@ bbox!(layout::AbstractLayout, bb::BoundingBox) = (layout.bbox = bb)
|
|||||||
Base.parent(layout::AbstractLayout) = layout.parent
|
Base.parent(layout::AbstractLayout) = layout.parent
|
||||||
parent_bbox(layout::AbstractLayout) = bbox(parent(layout))
|
parent_bbox(layout::AbstractLayout) = bbox(parent(layout))
|
||||||
|
|
||||||
# NOTE: these should be implemented for subplots in each backend!
|
# padding_w(layout::AbstractLayout) = left_padding(layout) + right_padding(layout)
|
||||||
# they represent the minimum size of the axes and guides
|
# padding_h(layout::AbstractLayout) = bottom_padding(layout) + top_padding(layout)
|
||||||
min_padding_left(layout::AbstractLayout) = 0mm
|
# padding(layout::AbstractLayout) = (padding_w(layout), padding_h(layout))
|
||||||
min_padding_top(layout::AbstractLayout) = 0mm
|
|
||||||
min_padding_right(layout::AbstractLayout) = 0mm
|
|
||||||
min_padding_bottom(layout::AbstractLayout) = 0mm
|
|
||||||
|
|
||||||
padding_w(layout::AbstractLayout) = left_padding(layout) + right_padding(layout)
|
update_position!(layout::AbstractLayout) = nothing
|
||||||
padding_h(layout::AbstractLayout) = bottom_padding(layout) + top_padding(layout)
|
update_child_bboxes!(layout::AbstractLayout, minimum_perimeter = [0mm,0mm,0mm,0mm]) = nothing
|
||||||
padding(layout::AbstractLayout) = (padding_w(layout), padding_h(layout))
|
|
||||||
|
|
||||||
_update_position!(layout::AbstractLayout) = nothing
|
|
||||||
update_child_bboxes!(layout::AbstractLayout) = nothing
|
|
||||||
|
|
||||||
width(layout::AbstractLayout) = width(layout.bbox)
|
width(layout::AbstractLayout) = width(layout.bbox)
|
||||||
height(layout::AbstractLayout) = height(layout.bbox)
|
height(layout::AbstractLayout) = height(layout.bbox)
|
||||||
@ -204,6 +197,12 @@ rightpad(layout::GridLayout) = layout.minpad[3]
|
|||||||
bottompad(layout::GridLayout) = layout.minpad[4]
|
bottompad(layout::GridLayout) = layout.minpad[4]
|
||||||
|
|
||||||
|
|
||||||
|
# here's how this works... first we recursively "update the minimum padding" (which
|
||||||
|
# means to calculate the minimum size needed from the edge of the subplot to plot area)
|
||||||
|
# for the whole layout tree. then we can compute the "padding borders" of this
|
||||||
|
# layout as the biggest padding of the children on the perimeter. then we need to
|
||||||
|
# recursively pass those borders back down the tree, one side at a time, but ONLY
|
||||||
|
# to those perimeter children.
|
||||||
|
|
||||||
# leftpad, toppad, rightpad, bottompad
|
# leftpad, toppad, rightpad, bottompad
|
||||||
function _update_min_padding!(layout::GridLayout)
|
function _update_min_padding!(layout::GridLayout)
|
||||||
@ -217,10 +216,11 @@ function _update_min_padding!(layout::GridLayout)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function _update_position!(layout::GridLayout)
|
function update_position!(layout::GridLayout)
|
||||||
map(_update_position!, layout.grid)
|
map(update_position!, layout.grid)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# some lengths are fixed... we have to split up the free space among the list v
|
||||||
function recompute_lengths(v)
|
function recompute_lengths(v)
|
||||||
# dump(v)
|
# dump(v)
|
||||||
tot = 0pct
|
tot = 0pct
|
||||||
@ -242,11 +242,11 @@ function recompute_lengths(v)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# recursively compute the bounding boxes for the layout and plotarea (relative to canvas!)
|
# recursively compute the bounding boxes for the layout and plotarea (relative to canvas!)
|
||||||
function update_child_bboxes!(layout::GridLayout)
|
function update_child_bboxes!(layout::GridLayout, minimum_perimeter = [0mm,0mm,0mm,0mm])
|
||||||
nr, nc = size(layout)
|
nr, nc = size(layout)
|
||||||
|
|
||||||
# create a matrix for each minimum padding direction
|
# # create a matrix for each minimum padding direction
|
||||||
_update_min_padding!(layout)
|
# _update_min_padding!(layout)
|
||||||
|
|
||||||
minpad_left = map(leftpad, layout.grid)
|
minpad_left = map(leftpad, layout.grid)
|
||||||
minpad_top = map(toppad, layout.grid)
|
minpad_top = map(toppad, layout.grid)
|
||||||
@ -263,6 +263,12 @@ function update_child_bboxes!(layout::GridLayout)
|
|||||||
pad_bottom = maximum(minpad_bottom, 2)
|
pad_bottom = maximum(minpad_bottom, 2)
|
||||||
# @show pad_left pad_top pad_right pad_bottom
|
# @show pad_left pad_top pad_right pad_bottom
|
||||||
|
|
||||||
|
# make sure the perimeter match the parent
|
||||||
|
pad_left[1] = max(pad_left[1], minimum_perimeter[1])
|
||||||
|
pad_top[1] = max(pad_top[1], minimum_perimeter[2])
|
||||||
|
pad_right[end] = max(pad_right[end], minimum_perimeter[3])
|
||||||
|
pad_bottom[end] = max(pad_bottom[end], minimum_perimeter[4])
|
||||||
|
|
||||||
# scale this up to the total padding in each direction
|
# scale this up to the total padding in each direction
|
||||||
total_pad_horizontal = sum(pad_left + pad_right)
|
total_pad_horizontal = sum(pad_left + pad_right)
|
||||||
total_pad_vertical = sum(pad_top + pad_bottom)
|
total_pad_vertical = sum(pad_top + pad_bottom)
|
||||||
@ -303,8 +309,17 @@ function update_child_bboxes!(layout::GridLayout)
|
|||||||
child_height = pad_top[r] + plotarea_height + pad_bottom[r]
|
child_height = pad_top[r] + plotarea_height + pad_bottom[r]
|
||||||
bbox!(child, BoundingBox(child_left, child_top, child_width, child_height))
|
bbox!(child, BoundingBox(child_left, child_top, child_width, child_height))
|
||||||
|
|
||||||
|
# this is the minimum perimeter as decided by this child's parent, so that
|
||||||
|
# all children on this border have the same value
|
||||||
|
min_child_perimeter = [
|
||||||
|
c == 1 ? layout.minpad[1] : 0mm,
|
||||||
|
r == 1 ? layout.minpad[2] : 0mm,
|
||||||
|
c == nc ? layout.minpad[3] : 0mm,
|
||||||
|
r == nr ? layout.minpad[4] : 0mm
|
||||||
|
]
|
||||||
|
|
||||||
# recursively update the child's children
|
# recursively update the child's children
|
||||||
update_child_bboxes!(child)
|
update_child_bboxes!(child, min_child_perimeter)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -376,40 +391,21 @@ end
|
|||||||
|
|
||||||
layout_args(huh) = error("unhandled layout type $(typeof(huh)): $huh")
|
layout_args(huh) = error("unhandled layout type $(typeof(huh)): $huh")
|
||||||
|
|
||||||
# # pass the layout arg through
|
|
||||||
# function build_layout(d::KW)
|
# ----------------------------------------------------------------------
|
||||||
# build_layout(get(d, :layout, default(:layout)))
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# function build_layout(n::Integer)
|
|
||||||
# nr, nc = compute_gridsize(n, -1, -1)
|
|
||||||
# build_layout(GridLayout(nr, nc), n)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# function build_layout{I<:Integer}(sztup::NTuple{2,I})
|
|
||||||
# nr, nc = sztup
|
|
||||||
# build_layout(GridLayout(nr, nc))
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# function build_layout{I<:Integer}(sztup::NTuple{3,I})
|
|
||||||
# n, nr, nc = sztup
|
|
||||||
# nr, nc = compute_gridsize(n, nr, nc)
|
|
||||||
# build_layout(GridLayout(nr, nc), n)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# # compute number of subplots
|
|
||||||
# function build_layout(layout::GridLayout)
|
|
||||||
# # recursively get the size of the grid
|
|
||||||
# n = calc_num_subplots(layout)
|
|
||||||
# build_layout(layout, n)
|
|
||||||
# end
|
|
||||||
|
|
||||||
function build_layout(args...)
|
function build_layout(args...)
|
||||||
layout, n = layout_args(args...)
|
layout, n = layout_args(args...)
|
||||||
build_layout(layout, n)
|
build_layout(layout, n)
|
||||||
end
|
end
|
||||||
|
|
||||||
# n is the number of subplots
|
# # just a single subplot
|
||||||
|
# function build_layout(sp::Subplot, n::Integer)
|
||||||
|
# sp, Subplot[sp], SubplotMap(gensym() => sp)
|
||||||
|
# end
|
||||||
|
|
||||||
|
# n is the number of subplots... build a grid and initialize the inner subplots recursively
|
||||||
function build_layout(layout::GridLayout, n::Integer)
|
function build_layout(layout::GridLayout, n::Integer)
|
||||||
nr, nc = size(layout)
|
nr, nc = size(layout)
|
||||||
subplots = Subplot[]
|
subplots = Subplot[]
|
||||||
@ -644,7 +640,9 @@ end
|
|||||||
function link_axes!(a::AbstractArray{AbstractLayout}, axissym::Symbol)
|
function link_axes!(a::AbstractArray{AbstractLayout}, axissym::Symbol)
|
||||||
subplots = filter(l -> isa(l, Subplot), a)
|
subplots = filter(l -> isa(l, Subplot), a)
|
||||||
axes = [sp.attr[axissym] for sp in subplots]
|
axes = [sp.attr[axissym] for sp in subplots]
|
||||||
link_axes!(axes...)
|
if length(axes) > 0
|
||||||
|
link_axes!(axes...)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# don't do anything for most layout types
|
# don't do anything for most layout types
|
||||||
|
|||||||
48
src/plot.jl
48
src/plot.jl
@ -102,6 +102,25 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# just in case the backend needs to set up the plot (make it current or something)
|
||||||
|
_prepare_plot_object(plt)
|
||||||
|
|
||||||
|
# first apply any args for the subplots
|
||||||
|
for (idx,sp) in enumerate(plt.subplots)
|
||||||
|
_update_subplot_args(plt, sp, d, idx, remove_pair = false)
|
||||||
|
end
|
||||||
|
|
||||||
|
# # now we can get rid of the axis keys without a letter
|
||||||
|
# for k in keys(_axis_defaults)
|
||||||
|
# delete!(d, k)
|
||||||
|
# for letter in (:x,:y,:z)
|
||||||
|
# delete!(d, Symbol(letter,k))
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
|
||||||
|
# do we need to link any axes together?
|
||||||
|
link_axes!(plt.layout, plt[:link])
|
||||||
|
|
||||||
# finish up
|
# finish up
|
||||||
current(plt)
|
current(plt)
|
||||||
if get(d, :show, default(:show))
|
if get(d, :show, default(:show))
|
||||||
@ -305,17 +324,17 @@ function _plot!(plt::Plot, d::KW, args...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# merge in anything meant for plot/subplot
|
# merge in anything meant for plot/subplot/axis
|
||||||
for kw in kw_list
|
for kw in kw_list
|
||||||
for (k,v) in kw
|
for (k,v) in kw
|
||||||
for defdict in (_plot_defaults, _subplot_defaults)
|
for defdict in (_plot_defaults,
|
||||||
|
_subplot_defaults,
|
||||||
|
_axis_defaults,
|
||||||
|
_axis_defaults_byletter)
|
||||||
if haskey(defdict, k)
|
if haskey(defdict, k)
|
||||||
d[k] = pop!(kw, k)
|
d[k] = pop!(kw, k)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# if haskey(_plot_defaults, k) || haskey(_subplot_defaults, k)
|
|
||||||
# d[k] = v
|
|
||||||
# end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -351,9 +370,6 @@ function _plot!(plt::Plot, d::KW, args...)
|
|||||||
# this is it folks!
|
# this is it folks!
|
||||||
# TODO: we probably shouldn't use i for tracking series index, but rather explicitly track it in recipes
|
# 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)
|
for (i,kw) in enumerate(kw_list)
|
||||||
# if !(get(kw, :seriestype, :none) in (:xerror, :yerror))
|
|
||||||
# plt.n += 1
|
|
||||||
# end
|
|
||||||
command_idx = kw[:series_plotindex] - kw_list[1][:series_plotindex] + 1
|
command_idx = kw[:series_plotindex] - kw_list[1][:series_plotindex] + 1
|
||||||
|
|
||||||
# get the Subplot object to which the series belongs
|
# get the Subplot object to which the series belongs
|
||||||
@ -393,15 +409,6 @@ function _plot!(plt::Plot, d::KW, args...)
|
|||||||
_apply_series_recipe(plt, kw)
|
_apply_series_recipe(plt, kw)
|
||||||
end
|
end
|
||||||
|
|
||||||
# # everything is processed, time to compute the layout bounding boxes
|
|
||||||
# _before_layout_calcs(plt)
|
|
||||||
# w, h = plt.attr[:size]
|
|
||||||
# plt.layout.bbox = BoundingBox(0mm, 0mm, w*px, h*px)
|
|
||||||
# update_child_bboxes!(plt.layout)
|
|
||||||
#
|
|
||||||
# # TODO just need to pass plt... and we should do all non-series updates here
|
|
||||||
# _update_plot_object(plt)
|
|
||||||
|
|
||||||
current(plt)
|
current(plt)
|
||||||
|
|
||||||
# note: lets ignore the show param and effectively use the semicolon at the end of the REPL statement
|
# note: lets ignore the show param and effectively use the semicolon at the end of the REPL statement
|
||||||
@ -429,8 +436,15 @@ function prepare_output(plt::Plot)
|
|||||||
|
|
||||||
w, h = plt.attr[:size]
|
w, h = plt.attr[:size]
|
||||||
plt.layout.bbox = BoundingBox(0mm, 0mm, w*px, h*px)
|
plt.layout.bbox = BoundingBox(0mm, 0mm, w*px, h*px)
|
||||||
|
|
||||||
|
# One pass down and back up the tree to compute the minimum padding
|
||||||
|
# of the children on the perimeter. This is an backend callback.
|
||||||
|
_update_min_padding!(plt.layout)
|
||||||
|
|
||||||
|
# now another pass down, to update the bounding boxes
|
||||||
update_child_bboxes!(plt.layout)
|
update_child_bboxes!(plt.layout)
|
||||||
|
|
||||||
|
# the backend callback, to reposition subplots, etc
|
||||||
_update_plot_object(plt)
|
_update_plot_object(plt)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user