redo the bbox logic
This commit is contained in:
parent
80b9115393
commit
0d237028e7
@ -249,14 +249,22 @@ drawax(ax) = ax[:draw](renderer(ax[:get_figure]()))
|
|||||||
# BoundingBox(left, bottom, right, top)
|
# BoundingBox(left, bottom, right, top)
|
||||||
# end
|
# end
|
||||||
|
|
||||||
|
function py_bbox_fig(obj)
|
||||||
|
fl, fr, fb, ft = fig[:get_window_extent]()
|
||||||
|
BoundingBox(0px, 0px, (fr-fl)*px, (ft-fb)*px)
|
||||||
|
end
|
||||||
|
|
||||||
|
# compute a bounding box (with origin top-left), however pyplot gives coords with origin bottom-left
|
||||||
function py_bbox(obj)
|
function py_bbox(obj)
|
||||||
|
fl, fr, fb, ft = py_bbox_fig(obj[:get_figure]())
|
||||||
l, r, b, t = obj[:get_window_extent]()[:get_points]()
|
l, r, b, t = obj[:get_window_extent]()[:get_points]()
|
||||||
BoundingBox(l*px, b*px, (r-l)*px, (t-b)*px)
|
BoundingBox(l*px, (ft-t)*px, (r-l)*px, (t-b)*px)
|
||||||
|
# BoundingBox(l*px, (t*px, (r-l)*px, (t-b)*px)
|
||||||
end
|
end
|
||||||
|
|
||||||
# bbox_from_pyplot(obj) =
|
# bbox_from_pyplot(obj) =
|
||||||
|
|
||||||
py_bbox_fig(plt::Plot) = py_bbox(plt.o)
|
py_bbox_fig(plt::Plot) = py_bbox_fig(plt.o)
|
||||||
|
|
||||||
function py_bbox_ticks(ax, letter)
|
function py_bbox_ticks(ax, letter)
|
||||||
# fig = ax[:get_figure]()
|
# fig = ax[:get_figure]()
|
||||||
@ -289,31 +297,40 @@ function py_bbox_title(ax)
|
|||||||
py_bbox(ax[:title])
|
py_bbox(ax[:title])
|
||||||
end
|
end
|
||||||
|
|
||||||
xaxis_height(sp::Subplot{PyPlotBackend}) = height(py_bbox_axis(sp.o,"x"))
|
# TODO: need to compute each of these by subtracting the plotarea position from
|
||||||
yaxis_width(sp::Subplot{PyPlotBackend}) = width(py_bbox_axis(sp.o,"y"))
|
# the most extreme guide/axis in each direction. Can pass method (left,top,right,bottom)
|
||||||
title_height(sp::Subplot{PyPlotBackend}) = height(py_bbox_title(sp.o))
|
# and aggregation (minimum or maximum) into a method to do this.
|
||||||
|
|
||||||
# note: this overrides the default version to allow for labels that stick out the sides
|
min_padding_left(layout::Subplot{PyPlotBackend}) = 0mm
|
||||||
# bounding box (relative to canvas) for plot area
|
min_padding_top(layout::Subplot{PyPlotBackend}) = 0mm
|
||||||
# note: we assume the x axis is on the left, and y axis is on the bottom
|
min_padding_right(layout::Subplot{PyPlotBackend}) = 0mm
|
||||||
# TODO: really the padding below should be part of the freespace calc, and we should probably
|
min_padding_bottom(layout::Subplot{PyPlotBackend}) = 0mm
|
||||||
# cache the plotarea bbox while we're doing that (need to add plotarea field to Subplot)
|
|
||||||
function plotarea_bbox(sp::Subplot{PyPlotBackend})
|
# xaxis_height(sp::Subplot{PyPlotBackend}) = height(py_bbox_axis(sp.o,"x"))
|
||||||
ax = sp.o
|
# yaxis_width(sp::Subplot{PyPlotBackend}) = width(py_bbox_axis(sp.o,"y"))
|
||||||
plot_bb = py_bbox(ax)
|
# title_height(sp::Subplot{PyPlotBackend}) = height(py_bbox_title(sp.o))
|
||||||
xbb = py_bbox_axis(ax, "x")
|
|
||||||
ybb = py_bbox_axis(ax, "y")
|
# # note: this overrides the default version to allow for labels that stick out the sides
|
||||||
titbb = py_bbox_title(ax)
|
# # bounding box (relative to canvas) for plot area
|
||||||
items = [xbb, ybb, titbb]
|
# # note: we assume the x axis is on the left, and y axis is on the bottom
|
||||||
# TODO: add in margin/padding from sp.attr
|
# # TODO: really the padding below should be part of the freespace calc, and we should probably
|
||||||
leftpad = max(0mm, left(plot_bb) - minimum(map(left, items)))
|
# # cache the plotarea bbox while we're doing that (need to add plotarea field to Subplot)
|
||||||
bottompad = max(0mm, bottom(plot_bb) - minimum(map(bottom, items)))
|
# function plotarea_bbox(sp::Subplot{PyPlotBackend})
|
||||||
rightpad = max(0mm, maximum(map(right, items)) - right(plot_bb))
|
# ax = sp.o
|
||||||
toppad = max(0mm, maximum(map(top, items)) - top(plot_bb))
|
# plot_bb = py_bbox(ax)
|
||||||
crop(bbox(sp), BoundingBox(leftpad, bottompad,
|
# xbb = py_bbox_axis(ax, "x")
|
||||||
width(sp) - rightpad - leftpad,
|
# ybb = py_bbox_axis(ax, "y")
|
||||||
height(sp) - toppad - bottompad))
|
# titbb = py_bbox_title(ax)
|
||||||
end
|
# items = [xbb, ybb, titbb]
|
||||||
|
# # TODO: add in margin/padding from sp.attr
|
||||||
|
# leftpad = max(0mm, left(plot_bb) - minimum(map(left, items)))
|
||||||
|
# bottompad = max(0mm, bottom(plot_bb) - minimum(map(bottom, items)))
|
||||||
|
# rightpad = max(0mm, maximum(map(right, items)) - right(plot_bb))
|
||||||
|
# toppad = max(0mm, maximum(map(top, items)) - top(plot_bb))
|
||||||
|
# crop(bbox(sp), BoundingBox(leftpad, bottompad,
|
||||||
|
# width(sp) - rightpad - leftpad,
|
||||||
|
# height(sp) - toppad - bottompad))
|
||||||
|
# end
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -1316,7 +1333,7 @@ function finalizePlot(plt::Plot{PyPlotBackend})
|
|||||||
end
|
end
|
||||||
drawfig(plt.o)
|
drawfig(plt.o)
|
||||||
plt.layout.bbox = py_bbox_fig(plt)
|
plt.layout.bbox = py_bbox_fig(plt)
|
||||||
upadte_child_bboxes!(plt.layout)
|
update_child_bboxes!(plt.layout)
|
||||||
update_position!(plt.layout)
|
update_position!(plt.layout)
|
||||||
PyPlot.draw()
|
PyPlot.draw()
|
||||||
end
|
end
|
||||||
|
|||||||
@ -200,6 +200,11 @@ function _plot!(plt::Plot, d::KW, args...)
|
|||||||
# just in case the backend needs to set up the plot (make it current or something)
|
# just in case the backend needs to set up the plot (make it current or something)
|
||||||
_before_add_series(plt)
|
_before_add_series(plt)
|
||||||
|
|
||||||
|
# first apply any args for the subplots
|
||||||
|
for sp in plt.subplots
|
||||||
|
_update_subplot_args(plt, sp, d)
|
||||||
|
end
|
||||||
|
|
||||||
# the grouping mechanism is a recipe on a GroupBy object
|
# the grouping mechanism is a recipe on a GroupBy object
|
||||||
# we simply add the GroupBy object to the front of the args list to allow
|
# we simply add the GroupBy object to the front of the args list to allow
|
||||||
# the recipe to be applied
|
# the recipe to be applied
|
||||||
@ -316,7 +321,7 @@ function _plot!(plt::Plot, d::KW, args...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# get the Subplot object to which the series belongs
|
# get the Subplot object to which the series belongs
|
||||||
sp = slice_arg(get(kw,:subplot,1), i)
|
sp = slice_arg(get(kw, :subplot, :auto), i)
|
||||||
if sp == :auto
|
if sp == :auto
|
||||||
sp = 1 # TODO: something useful
|
sp = 1 # TODO: something useful
|
||||||
end
|
end
|
||||||
|
|||||||
229
src/subplots.jl
229
src/subplots.jl
@ -11,21 +11,26 @@ 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))
|
||||||
|
|
||||||
# this is a calculation of the percentage of free space available in the canvas
|
# # this is a calculation of the percentage of free space available in the canvas
|
||||||
# after accounting for the size of guides and axes
|
# # after accounting for the size of guides and axes
|
||||||
free_size(layout::AbstractLayout) = (free_width(layout), free_height(layout))
|
# free_size(layout::AbstractLayout) = (free_width(layout), free_height(layout))
|
||||||
free_width(layout::AbstractLayout) = width(layout.bbox) - used_width(layout)
|
# free_width(layout::AbstractLayout) = width(layout.bbox) - used_width(layout)
|
||||||
free_height(layout::AbstractLayout) = height(layout.bbox) - used_height(layout)
|
# free_height(layout::AbstractLayout) = height(layout.bbox) - used_height(layout)
|
||||||
|
|
||||||
used_size(layout::AbstractLayout) = (used_width(layout), used_height(layout))
|
# NOTE: these should be implemented for subplots in each backend!
|
||||||
|
# they represent the minimum size of the axes and guides
|
||||||
|
min_padding_left(layout::AbstractLayout) = 0mm
|
||||||
|
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)
|
||||||
|
padding_h(layout::AbstractLayout) = bottom_padding(layout) + top_padding(layout)
|
||||||
|
padding(layout::AbstractLayout) = (padding_w(layout), padding_h(layout))
|
||||||
|
|
||||||
# # compute the area which is available to this layout
|
|
||||||
# function bbox_pct(layout::AbstractLayout)
|
|
||||||
#
|
|
||||||
# end
|
|
||||||
|
|
||||||
update_position!(layout::AbstractLayout) = nothing
|
update_position!(layout::AbstractLayout) = nothing
|
||||||
upadte_child_bboxes!(layout::AbstractLayout) = nothing
|
update_child_bboxes!(layout::AbstractLayout) = nothing
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
@ -33,9 +38,6 @@ Base.size(layout::EmptyLayout) = (0,0)
|
|||||||
Base.length(layout::EmptyLayout) = 0
|
Base.length(layout::EmptyLayout) = 0
|
||||||
Base.getindex(layout::EmptyLayout, r::Int, c::Int) = nothing
|
Base.getindex(layout::EmptyLayout, r::Int, c::Int) = nothing
|
||||||
|
|
||||||
used_width(layout::EmptyLayout) = 0pct
|
|
||||||
used_height(layout::EmptyLayout) = 0pct
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
@ -54,8 +56,8 @@ Base.length(sp::Subplot) = 1
|
|||||||
Base.getindex(sp::Subplot, r::Int, c::Int) = sp
|
Base.getindex(sp::Subplot, r::Int, c::Int) = sp
|
||||||
|
|
||||||
|
|
||||||
used_width(sp::Subplot) = yaxis_width(sp)
|
# used_width(sp::Subplot) = yaxis_width(sp)
|
||||||
used_height(sp::Subplot) = xaxis_height(sp) + title_height(sp)
|
# used_height(sp::Subplot) = xaxis_height(sp) + title_height(sp)
|
||||||
|
|
||||||
# used_width(subplot::Subplot) = error("used_width(::Subplot) must be implemented by each backend")
|
# used_width(subplot::Subplot) = error("used_width(::Subplot) must be implemented by each backend")
|
||||||
# used_height(subplot::Subplot) = error("used_height(::Subplot) must be implemented by each backend")
|
# used_height(subplot::Subplot) = error("used_height(::Subplot) must be implemented by each backend")
|
||||||
@ -63,14 +65,14 @@ used_height(sp::Subplot) = xaxis_height(sp) + title_height(sp)
|
|||||||
# # this should return a bounding box (relative to the canvas) for the plot area (inside the spines/ticks)
|
# # this should return a bounding box (relative to the canvas) for the plot area (inside the spines/ticks)
|
||||||
# plotarea_bbox(subplot::Subplot) = error("plotarea_bbox(::Subplot) must be implemented by each backend")
|
# plotarea_bbox(subplot::Subplot) = error("plotarea_bbox(::Subplot) must be implemented by each backend")
|
||||||
|
|
||||||
# bounding box (relative to canvas) for plot area
|
# # 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
|
# # note: we assume the x axis is on the left, and y axis is on the bottom
|
||||||
function plotarea_bbox(sp::Subplot)
|
# function plotarea_bbox(sp::Subplot)
|
||||||
xh = xaxis_height(sp)
|
# xh = xaxis_height(sp)
|
||||||
yw = yaxis_width(sp)
|
# yw = yaxis_width(sp)
|
||||||
crop(bbox(sp), BoundingBox(yw, xh, width(sp) - yw,
|
# crop(bbox(sp), BoundingBox(yw, xh, width(sp) - yw,
|
||||||
height(sp) - xh - title_height(sp)))
|
# height(sp) - xh - title_height(sp)))
|
||||||
end
|
# end
|
||||||
|
|
||||||
# NOTE: this is unnecessary I think as it is the same as bbox(::Subplot)
|
# NOTE: this is unnecessary I think as it is the same as bbox(::Subplot)
|
||||||
# # this should return a bounding box (relative to the canvas) for the whole subplot (plotarea, ticks, and guides)
|
# # this should return a bounding box (relative to the canvas) for the whole subplot (plotarea, ticks, and guides)
|
||||||
@ -85,80 +87,145 @@ function Base.setindex!(layout::GridLayout, v, r::Int, c::Int)
|
|||||||
layout.grid[r,c] = v
|
layout.grid[r,c] = v
|
||||||
end
|
end
|
||||||
|
|
||||||
function used_width(layout::GridLayout)
|
min_padding_left(layout::GridLayout) = maximum(map(min_padding_left, layout.grid[:,1]))
|
||||||
w = 0mm
|
min_padding_top(layout::GridLayout) = maximum(map(min_padding_top, layout.grid[1,:]))
|
||||||
nr,nc = size(layout)
|
min_padding_right(layout::GridLayout) = maximum(map(min_padding_right, layout.grid[:,end]))
|
||||||
for c=1:nc
|
min_padding_bottom(layout::GridLayout) = maximum(map(min_padding_bottom, layout.grid[end,:]))
|
||||||
@show w
|
|
||||||
w += maximum([used_width(layout[r,c]) for r=1:nr])
|
|
||||||
for r=1:nr
|
|
||||||
@show used_width(layout[r,c])
|
|
||||||
end
|
|
||||||
@show w
|
|
||||||
end
|
|
||||||
w
|
|
||||||
end
|
|
||||||
|
|
||||||
function used_height(layout::GridLayout)
|
# function used_width(layout::GridLayout)
|
||||||
h = 0mm
|
# w = 0mm
|
||||||
nr,nc = size(layout)
|
# nr,nc = size(layout)
|
||||||
for r=1:nr
|
# for c=1:nc
|
||||||
h += maximum([used_height(layout[r,c]) for c=1:nc])
|
# @show w
|
||||||
end
|
# w += maximum([used_width(layout[r,c]) for r=1:nr])
|
||||||
h
|
# for r=1:nr
|
||||||
end
|
# @show used_width(layout[r,c])
|
||||||
|
# end
|
||||||
|
# @show w
|
||||||
|
# end
|
||||||
|
# w
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# function used_height(layout::GridLayout)
|
||||||
|
# h = 0mm
|
||||||
|
# nr,nc = size(layout)
|
||||||
|
# for r=1:nr
|
||||||
|
# h += maximum([used_height(layout[r,c]) for c=1:nc])
|
||||||
|
# end
|
||||||
|
# h
|
||||||
|
# end
|
||||||
|
|
||||||
update_position!(layout::GridLayout) = map(update_position!, layout.grid)
|
update_position!(layout::GridLayout) = map(update_position!, layout.grid)
|
||||||
|
|
||||||
# a recursive method to first compute the free space by bubbling the free space
|
|
||||||
# up the tree, then assigning bounding boxes according to height/width percentages
|
# recursively compute the bounding boxes for the layout and plotarea (relative to canvas!)
|
||||||
# note: this should be called after all axis objects are updated to re-compute the
|
function update_child_bboxes!(layout::GridLayout)
|
||||||
# bounding boxes for the layout tree
|
|
||||||
function upadte_child_bboxes!(layout::GridLayout) #, parent_bbox::BoundingBox = defaultbox)
|
|
||||||
# initialize the free space (per child!)
|
|
||||||
nr, nc = size(layout)
|
nr, nc = size(layout)
|
||||||
freew, freeh = free_size(layout)
|
|
||||||
@show freew, freeh
|
|
||||||
freew /= sum(layout.widths)
|
|
||||||
freeh /= sum(layout.heights)
|
|
||||||
@show freew, freeh
|
|
||||||
|
|
||||||
@show layout.bbox
|
# 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)
|
||||||
|
|
||||||
# TODO: this should really track used/free space for each row/column so that we can align plot areas properly
|
# get the max horizontal (left and right) padding over columns,
|
||||||
|
# and max vertical (bottom and top) padding over rows
|
||||||
|
# TODO: add extra padding here
|
||||||
|
pad_left = maximum(minpad_left, 1)
|
||||||
|
pad_top = maximum(minpad_top, 2)
|
||||||
|
pad_right = maximum(minpad_right, 1)
|
||||||
|
pad_bottom = maximum(minpad_bottom, 2)
|
||||||
|
|
||||||
# l, b = 0.0, 0.0
|
# scale this up to the total padding in each direction
|
||||||
rights = Measure[0mm for i=1:nc] #zeros(nc) .* pct
|
total_pad_horizontal = (pad_left + pad_right) * nc
|
||||||
bottoms = Measure[1pct for i=1:nr] # ones(nr) .* pct
|
total_pad_vertical = (pad_top + pad_bottom) * nr
|
||||||
|
|
||||||
|
# now we can compute the total plot area in each direction
|
||||||
|
total_plotarea_horizontal = width(layout) - total_pad_horizontal
|
||||||
|
total_plotarea_vertical = height(layout) - total_pad_vertical
|
||||||
|
|
||||||
|
# normalize widths/heights so they sum to 1
|
||||||
|
layout.widths ./ sum(layout.widths)
|
||||||
|
layout.heights ./ sum(layout.heights)
|
||||||
|
|
||||||
|
# we have all the data we need... lets compute the plot areas
|
||||||
for r=1:nr, c=1:nc
|
for r=1:nr, c=1:nc
|
||||||
# compute the child's bounding box relative to the parent
|
|
||||||
child = layout[r,c]
|
child = layout[r,c]
|
||||||
usedw, usedh = used_size(child)
|
|
||||||
@show r,c, usedw, usedh
|
|
||||||
|
|
||||||
plot_l = (c == 1 ? 0mm : rights[c-1])
|
# get the top-left corner of this child
|
||||||
plot_t = (r == 1 ? height(layout) : bottoms[r-1])
|
child_left = (c == 1 ? 0mm : right(layout[r, c-1])
|
||||||
# bottom = (r == 1 ? 0 : bottoms[r-1])
|
child_top = (r == 1 ? 0mm : top(layout[r-1, c]))
|
||||||
plot_w = freew * layout.widths[c]
|
|
||||||
plot_h = freeh * layout.heights[r]
|
|
||||||
right = plot_l + usedw + plot_w
|
|
||||||
bottom = plot_t - usedh - plot_h
|
|
||||||
# plot_t = bottom + usedh + freeh * layout.heights[r]
|
|
||||||
child_bbox = BoundingBox(plot_l, bottom, plot_w, plot_h)
|
|
||||||
@show child_bbox
|
|
||||||
|
|
||||||
rights[c] = right
|
# compute plot area
|
||||||
bottoms[r] = bottom
|
plotarea_left = child_left + pad_left[c]
|
||||||
|
plotarea_top = child_top + pad_top[r]
|
||||||
|
plotarea_width = total_pad_horizontal * layout.widths[c]
|
||||||
|
plotarea_height = total_pad_vertical * layout.heights[r]
|
||||||
|
child.plotarea = BoundingBox(plotarea_left, plotarea_top, plotarea_width, plotarea_height)
|
||||||
|
|
||||||
# then compute the bounding box relative to the canvas, and cache it in the child object
|
# compute child bbox
|
||||||
bbox!(child, crop(bbox(layout), child_bbox))
|
child_width = pad_left[c] + plotarea_width + pad_right[c]
|
||||||
@show child.bbox
|
child_height = pad_top[r] + plotarea_height + pad_bottom[r]
|
||||||
|
child.bbox = BoundingBox(child_left, child_top, child_width, child_height)
|
||||||
|
|
||||||
# now recursively update the child
|
# the bounding boxes are currently relative to the parent, but we need them relative to the canvas
|
||||||
upadte_child_bboxes!(child)
|
child.plotarea = crop(layout.bbox, child.plotarea)
|
||||||
|
child.bbox = crop(layout.bbox, child.plotarea)
|
||||||
|
|
||||||
|
# recursively update the child's children
|
||||||
|
update_child_bboxes!(child)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# # a recursive method to first compute the free space by bubbling the free space
|
||||||
|
# # up the tree, then assigning bounding boxes according to height/width percentages
|
||||||
|
# # note: this should be called after all axis objects are updated to re-compute the
|
||||||
|
# # bounding boxes for the layout tree
|
||||||
|
# function update_child_bboxes!(layout::GridLayout) #, parent_bbox::BoundingBox = defaultbox)
|
||||||
|
# # initialize the free space (per child!)
|
||||||
|
# nr, nc = size(layout)
|
||||||
|
# freew, freeh = free_size(layout)
|
||||||
|
# @show freew, freeh
|
||||||
|
# freew /= sum(layout.widths)
|
||||||
|
# freeh /= sum(layout.heights)
|
||||||
|
# @show freew, freeh
|
||||||
|
#
|
||||||
|
# @show layout.bbox
|
||||||
|
#
|
||||||
|
# # TODO: this should really track used/free space for each row/column so that we can align plot areas properly
|
||||||
|
#
|
||||||
|
# # l, b = 0.0, 0.0
|
||||||
|
# rights = Measure[0mm for i=1:nc] #zeros(nc) .* pct
|
||||||
|
# bottoms = Measure[0mm for i=1:nr] # ones(nr) .* pct
|
||||||
|
# for r=1:nr, c=1:nc
|
||||||
|
# # compute the child's bounding box relative to the parent
|
||||||
|
# child = layout[r,c]
|
||||||
|
# usedw, usedh = used_size(child)
|
||||||
|
# @show r,c, usedw, usedh
|
||||||
|
#
|
||||||
|
# plot_l = (c == 1 ? 0mm : rights[c-1])
|
||||||
|
# plot_t = (r == 1 ? height(layout) : bottoms[r-1])
|
||||||
|
# # bottom = (r == 1 ? 0 : bottoms[r-1])
|
||||||
|
# plot_w = freew * layout.widths[c]
|
||||||
|
# plot_h = freeh * layout.heights[r]
|
||||||
|
# right = plot_l + usedw + plot_w
|
||||||
|
# bottom = plot_t - usedh - plot_h
|
||||||
|
# # plot_t = bottom + usedh + freeh * layout.heights[r]
|
||||||
|
# child_bbox = BoundingBox(plot_l, bottom, plot_w, plot_h)
|
||||||
|
# @show child_bbox
|
||||||
|
#
|
||||||
|
# rights[c] = right
|
||||||
|
# bottoms[r] = bottom
|
||||||
|
#
|
||||||
|
# # then compute the bounding box relative to the canvas, and cache it in the child object
|
||||||
|
# bbox!(child, crop(bbox(layout), child_bbox))
|
||||||
|
# @show child.bbox
|
||||||
|
#
|
||||||
|
# # now recursively update the child
|
||||||
|
# update_child_bboxes!(child)
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
# return the top-level layout, a list of subplots, and a SubplotMap
|
# return the top-level layout, a list of subplots, and a SubplotMap
|
||||||
|
|||||||
26
src/types.jl
26
src/types.jl
@ -35,15 +35,7 @@ end
|
|||||||
# Layouts
|
# Layouts
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
# # wraps bounding box coords (percent of parent area)
|
# NOTE: (0,0) is the top-left !!!
|
||||||
# # NOTE: (0,0) is the bottom-left, and (1,1) is the top-right!
|
|
||||||
# immutable BoundingBox
|
|
||||||
# left::Float64
|
|
||||||
# bottom::Float64
|
|
||||||
# right::Float64
|
|
||||||
# top::Float64
|
|
||||||
# end
|
|
||||||
# BoundingBox() = BoundingBox(0,0,0,0)
|
|
||||||
|
|
||||||
import Measures
|
import Measures
|
||||||
import Measures: Length, AbsoluteLength, Measure, BoundingBox, mm, cm, inch, pt, width, height
|
import Measures: Length, AbsoluteLength, Measure, BoundingBox, mm, cm, inch, pt, width, height
|
||||||
@ -76,9 +68,9 @@ const defaultbox = BoundingBox(0mm, 0mm, 0mm, 0mm)
|
|||||||
|
|
||||||
|
|
||||||
left(bbox::BoundingBox) = bbox.x0[1]
|
left(bbox::BoundingBox) = bbox.x0[1]
|
||||||
bottom(bbox::BoundingBox) = bbox.x0[2]
|
top(bbox::BoundingBox) = bbox.x0[2]
|
||||||
right(bbox::BoundingBox) = left(bbox) + width(bbox)
|
right(bbox::BoundingBox) = left(bbox) + width(bbox)
|
||||||
top(bbox::BoundingBox) = bottom(bbox) + height(bbox)
|
bottom(bbox::BoundingBox) = top(bbox) + height(bbox)
|
||||||
Base.size(bbox::BoundingBox) = (width(bbox), height(bbox))
|
Base.size(bbox::BoundingBox) = (width(bbox), height(bbox))
|
||||||
|
|
||||||
# Base.(:*){T,N}(m1::Length{T,N}, m2::Length{T,N}) = Length{T,N}(m1.value * m2.value)
|
# Base.(:*){T,N}(m1::Length{T,N}, m2::Length{T,N}) = Length{T,N}(m1.value * m2.value)
|
||||||
@ -101,7 +93,7 @@ function Base.(:+)(bb1::BoundingBox, bb2::BoundingBox)
|
|||||||
b = min(bottom(bb1), bottom(bb2))
|
b = min(bottom(bb1), bottom(bb2))
|
||||||
r = max(right(bb1), right(bb2))
|
r = max(right(bb1), right(bb2))
|
||||||
t = max(top(bb1), top(bb2))
|
t = max(top(bb1), top(bb2))
|
||||||
BoundingBox(l, b, r-l, t-b)
|
BoundingBox(l, t, r-l, t-b)
|
||||||
end
|
end
|
||||||
|
|
||||||
# this creates a bounding box in the parent's scope, where the child bounding box
|
# this creates a bounding box in the parent's scope, where the child bounding box
|
||||||
@ -112,14 +104,14 @@ function crop(parent::BoundingBox, child::BoundingBox)
|
|||||||
# w = width(parent) * width(child)
|
# w = width(parent) * width(child)
|
||||||
# h = height(parent) * height(child)
|
# h = height(parent) * height(child)
|
||||||
l = left(parent) + left(child)
|
l = left(parent) + left(child)
|
||||||
b = bottom(parent) + bottom(child)
|
t = top(parent) + top(child)
|
||||||
w = width(child)
|
w = width(child)
|
||||||
h = height(child)
|
h = height(child)
|
||||||
BoundingBox(l, b, w, h)
|
BoundingBox(l, t, w, h)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Base.show(io::IO, bbox::BoundingBox)
|
function Base.show(io::IO, bbox::BoundingBox)
|
||||||
print(io, "BBox{l,b,r,t,w,h = $(left(bbox)), $(bottom(bbox)), $(right(bbox)), $(top(bbox)), $(width(bbox)), $(height(bbox))}")
|
print(io, "BBox{l,t,r,b,w,h = $(left(bbox)),$(top(bbox)), $(right(bbox)),$(bottom(bbox)), $(width(bbox)),$(height(bbox))}")
|
||||||
end
|
end
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
@ -149,9 +141,11 @@ end
|
|||||||
type Subplot{T<:AbstractBackend} <: AbstractLayout
|
type Subplot{T<:AbstractBackend} <: AbstractLayout
|
||||||
parent::AbstractLayout
|
parent::AbstractLayout
|
||||||
bbox::BoundingBox # the canvas area which is available to this subplot
|
bbox::BoundingBox # the canvas area which is available to this subplot
|
||||||
|
plotarea::BoundingBox # the part where the data goes
|
||||||
subplotargs::KW # args specific to this subplot
|
subplotargs::KW # args specific to this subplot
|
||||||
# axisviews::Vector{AxisView}
|
# axisviews::Vector{AxisView}
|
||||||
o # can store backend-specific data... like a pyplot ax
|
o # can store backend-specific data... like a pyplot ax
|
||||||
|
plt # the enclosing Plot object (can't give it a type because of no forward declarations)
|
||||||
|
|
||||||
# Subplot(parent = RootLayout(); attr = KW())
|
# Subplot(parent = RootLayout(); attr = KW())
|
||||||
end
|
end
|
||||||
@ -162,6 +156,8 @@ end
|
|||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
|
# TODO: i'll want a plotarea! method to set the plotarea only if the field exists
|
||||||
|
|
||||||
# nested, gridded layout with optional size percentages
|
# nested, gridded layout with optional size percentages
|
||||||
type GridLayout <: AbstractLayout
|
type GridLayout <: AbstractLayout
|
||||||
parent::AbstractLayout
|
parent::AbstractLayout
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user