working on layouts
This commit is contained in:
parent
c5bcae1e34
commit
ae1f5b8b06
@ -66,6 +66,7 @@ function _initialize_backend(::PyPlotBackend)
|
|||||||
const pyticker = PyPlot.pywrap(PyPlot.pyimport("matplotlib.ticker"))
|
const pyticker = PyPlot.pywrap(PyPlot.pyimport("matplotlib.ticker"))
|
||||||
const pycmap = PyPlot.pywrap(PyPlot.pyimport("matplotlib.cm"))
|
const pycmap = PyPlot.pywrap(PyPlot.pyimport("matplotlib.cm"))
|
||||||
const pynp = PyPlot.pywrap(PyPlot.pyimport("numpy"))
|
const pynp = PyPlot.pywrap(PyPlot.pyimport("numpy"))
|
||||||
|
const pytransforms = PyPlot.pywrap(PyPlot.pyimport("matplotlib.transforms"))
|
||||||
end
|
end
|
||||||
|
|
||||||
PyPlot.ioff()
|
PyPlot.ioff()
|
||||||
@ -220,20 +221,110 @@ function add_pyfixedformatter(cbar, vals::AVec)
|
|||||||
cbar[:update_ticks]()
|
cbar[:update_ticks]()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Figure utils -- F*** matplotlib for making me work so hard to figure this crap out
|
||||||
|
|
||||||
|
# the drawing surface
|
||||||
|
canvas(fig) = fig[:canvas]
|
||||||
|
|
||||||
|
# the object controlling draw commands
|
||||||
|
renderer(fig) = canvas(fig)[:get_renderer]()
|
||||||
|
|
||||||
|
# draw commands... paint the screen (probably updating internals too)
|
||||||
|
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]()
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
pybbox_pixels = obj[:get_window_extent]()
|
||||||
|
fig = obj[:get_figure]()
|
||||||
|
pybbox_pct = pybbox_pixels[:inverse_transformed](fig[:transFigure])
|
||||||
|
left, right, bottom, top = pybbox_pct[:get_points]()
|
||||||
|
BoundingBox(left, bottom, right, top)
|
||||||
|
end
|
||||||
|
|
||||||
|
# bbox_from_pyplot(obj) =
|
||||||
|
|
||||||
|
function bbox_ticks(ax, letter)
|
||||||
|
# fig = ax[:get_figure]()
|
||||||
|
# @show fig
|
||||||
|
labels = ax[symbol("get_"*letter*"ticklabels")]()
|
||||||
|
# @show labels
|
||||||
|
# bboxes = []
|
||||||
|
bbox_union = BoundingBox()
|
||||||
|
for lab in labels
|
||||||
|
# @show lab,lab[:get_text]()
|
||||||
|
bbox = 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)
|
||||||
|
end
|
||||||
|
|
||||||
|
# get a bounding box for the whole axis
|
||||||
|
function bbox_axis(ax, letter)
|
||||||
|
bbox_ticks(ax, letter) + bbox_axislabel(ax, letter)
|
||||||
|
end
|
||||||
|
|
||||||
|
# get a bounding box for the title area
|
||||||
|
function bbox_title(ax)
|
||||||
|
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))
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# function used_width(sp::Subplot{PyPlotBackend})
|
||||||
|
# ax = sp.o
|
||||||
|
# width(bbox_axis(ax,"y"))
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# function used_height(sp::Subplot{PyPlotBackend})
|
||||||
|
# ax = sp.o
|
||||||
|
# height(bbox_axis(ax,"x")) + height(bbox_title(ax))
|
||||||
|
# end
|
||||||
|
|
||||||
|
|
||||||
|
# # bounding box (relative to canvas) for plot area
|
||||||
|
# function plotarea_bbox(sp::Subplot{PyPlotBackend})
|
||||||
|
# crop(bbox(sp), BoundingBox())
|
||||||
|
# end
|
||||||
|
|
||||||
|
function update_position!(sp::Subplot{PyPlotBackend})
|
||||||
|
ax = sp.o
|
||||||
|
bb = plotarea_bbox(sp)
|
||||||
|
ax[:set_position]([f(bb) for f in (left, bottom, width, height)])
|
||||||
|
end
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
function getAxis(plt::Plot{PyPlotBackend}, subplot::Subplot = plt.subplots[1])
|
function getAxis(plt::Plot{PyPlotBackend}, subplot::Subplot = plt.subplots[1])
|
||||||
if subplot.o == nothing
|
if subplot.o == nothing
|
||||||
@show subplot
|
@show subplot
|
||||||
fig = plt.o
|
fig = plt.o
|
||||||
@show plt
|
@show fig
|
||||||
# if fig == nothing
|
# if fig == nothing
|
||||||
# fig =
|
# fig =
|
||||||
# TODO: actual coords?
|
# TODO: actual coords?
|
||||||
# NOTE: might want to use ax[:get_tightbbox](ax[:get_renderer_cache]()) to calc size of guides?
|
# 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])
|
# 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
|
# left, bottom, width, height = 0.3, 0.3, 0.5, 0.5
|
||||||
ax = fig[:add_axes]([left, bottom, width, height])
|
|
||||||
|
# init to the full canvas, then we can set_position later
|
||||||
|
ax = fig[:add_axes]([0,0,1,1])
|
||||||
subplot.o = ax
|
subplot.o = ax
|
||||||
end
|
end
|
||||||
subplot.o
|
subplot.o
|
||||||
@ -1183,6 +1274,9 @@ function finalizePlot(plt::Plot{PyPlotBackend})
|
|||||||
ax = getLeftAxis(plt)
|
ax = getLeftAxis(plt)
|
||||||
addPyPlotLegend(plt, ax)
|
addPyPlotLegend(plt, ax)
|
||||||
updateAxisColors(ax, plt.plotargs)
|
updateAxisColors(ax, plt.plotargs)
|
||||||
|
drawfig(plt.o)
|
||||||
|
update_bboxes!(plt.layout)
|
||||||
|
update_position!(plt.layout)
|
||||||
PyPlot.draw()
|
PyPlot.draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -47,15 +47,15 @@ function plot(args...; kw...)
|
|||||||
d = KW(kw)
|
d = KW(kw)
|
||||||
preprocessArgs!(d)
|
preprocessArgs!(d)
|
||||||
|
|
||||||
layout = pop!(d, :layout, Subplot())
|
layout, subplots, spmap = build_layout(pop!(d, :layout, :auto))
|
||||||
subplots = Subplot[layout] # TODO: build full list
|
# subplots = Subplot[layout] # TODO: build full list
|
||||||
smap = SubplotMap(1 => layout) # TODO: actually build a map
|
# smap = SubplotMap(1 => layout) # TODO: actually build a map
|
||||||
|
|
||||||
# TODO: this seems wrong... I only call getPlotArgs when creating a new plot??
|
# TODO: this seems wrong... I only call getPlotArgs when creating a new plot??
|
||||||
plotargs = merge(d, getPlotArgs(pkg, d, 1))
|
plotargs = merge(d, getPlotArgs(pkg, d, 1))
|
||||||
# plt = _create_plot(pkg, plotargs) # create a new, blank plot
|
# plt = _create_plot(pkg, plotargs) # create a new, blank plot
|
||||||
|
|
||||||
plt = Plot(nothing, pkg, 0, plotargs, Series[], subplots, smap, layout)
|
plt = Plot(nothing, pkg, 0, plotargs, Series[], subplots, spmap, layout)
|
||||||
plt.o = _create_backend_figure(plt)
|
plt.o = _create_backend_figure(plt)
|
||||||
|
|
||||||
# now update the plot
|
# now update the plot
|
||||||
|
|||||||
175
src/subplots.jl
175
src/subplots.jl
@ -1,23 +1,188 @@
|
|||||||
|
|
||||||
|
|
||||||
|
left(bbox::BoundingBox) = bbox.left
|
||||||
|
bottom(bbox::BoundingBox) = bbox.bottom
|
||||||
|
right(bbox::BoundingBox) = bbox.right
|
||||||
|
top(bbox::BoundingBox) = bbox.top
|
||||||
|
width(bbox::BoundingBox) = bbox.right - bbox.left
|
||||||
|
height(bbox::BoundingBox) = bbox.top - bbox.bottom
|
||||||
|
|
||||||
|
Base.size(bbox::BoundingBox) = (width(bbox), height(bbox))
|
||||||
|
|
||||||
|
# union together bounding boxes
|
||||||
|
function Base.(:+)(bb1::BoundingBox, bb2::BoundingBox)
|
||||||
|
# empty boxes don't change the union
|
||||||
|
if width(bb1) <= 0 || height(bb1) <= 0
|
||||||
|
return bb2
|
||||||
|
elseif width(bb2) <= 0 || height(bb2) <= 0
|
||||||
|
return bb1
|
||||||
|
end
|
||||||
|
BoundingBox(
|
||||||
|
min(bb1.left, bb2.left),
|
||||||
|
min(bb1.bottom, bb2.bottom),
|
||||||
|
max(bb1.right, bb2.right),
|
||||||
|
max(bb1.top, bb2.top)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# this creates a bounding box in the parent's scope, where the child bounding box
|
||||||
|
# is relative to the parent
|
||||||
|
function crop(parent::BoundingBox, child::BoundingBox)
|
||||||
|
l = left(parent) + width(parent) * left(child)
|
||||||
|
w = width(parent) * width(child)
|
||||||
|
b = bottom(parent) + height(parent) * bottom(child)
|
||||||
|
h = height(parent) * height(child)
|
||||||
|
BoundingBox(l, b, l+w, b+h)
|
||||||
|
end
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
# this is the available area for drawing everything in this layout... as percentages of total canvas
|
||||||
|
bbox(layout::AbstractLayout) = layout.bbox
|
||||||
|
bbox!(layout::AbstractLayout, bb::BoundingBox) = (layout.bbox = bb)
|
||||||
|
|
||||||
|
# layouts are recursive, tree-like structures, and most will have a parent field
|
||||||
|
Base.parent(layout::AbstractLayout) = layout.parent
|
||||||
|
parent_bbox(layout::AbstractLayout) = bbox(parent(layout))
|
||||||
|
|
||||||
|
# this is a calculation of the percentage of free space available in the canvas
|
||||||
|
# after accounting for the size of guides and axes
|
||||||
|
free_size(layout::AbstractLayout) = (free_width(layout), free_height(layout))
|
||||||
|
free_width(layout::AbstractLayout) = 1.0 - used_width(layout)
|
||||||
|
free_height(layout::AbstractLayout) = 1.0 - used_height(layout)
|
||||||
|
|
||||||
|
used_size(layout::AbstractLayout) = (used_width(layout), used_height(layout))
|
||||||
|
|
||||||
|
# # compute the area which is available to this layout
|
||||||
|
# function bbox_pct(layout::AbstractLayout)
|
||||||
|
#
|
||||||
|
# end
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
Base.size(layout::EmptyLayout) = (0,0)
|
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) = 0.0
|
||||||
|
used_height(layout::EmptyLayout) = 0.0
|
||||||
|
|
||||||
Base.size(layout::RootLayout) = (1,1)
|
update_position!(layout::EmptyLayout) = nothing
|
||||||
Base.length(layout::RootLayout) = 1
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Base.parent(::RootLayout) = nothing
|
||||||
|
parent_bbox(::RootLayout) = BoundingBox(0,0,1,1)
|
||||||
|
bbox(::RootLayout) = BoundingBox(0,0,1,1)
|
||||||
|
|
||||||
|
# Base.size(layout::RootLayout) = (1,1)
|
||||||
|
# Base.length(layout::RootLayout) = 1
|
||||||
# Base.getindex(layout::RootLayout, r::Int, c::Int) = layout.child
|
# Base.getindex(layout::RootLayout, r::Int, c::Int) = layout.child
|
||||||
|
|
||||||
Base.size(subplot::Subplot) = (1,1)
|
# ----------------------------------------------------------------------
|
||||||
Base.length(subplot::Subplot) = 1
|
|
||||||
Base.getindex(subplot::Subplot, r::Int, c::Int) = subplot
|
|
||||||
|
|
||||||
|
Base.size(sp::Subplot) = (1,1)
|
||||||
|
Base.length(sp::Subplot) = 1
|
||||||
|
Base.getindex(sp::Subplot, r::Int, c::Int) = sp
|
||||||
|
|
||||||
|
|
||||||
|
used_width(sp::Subplot) = yaxis_width(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_height(subplot::Subplot) = error("used_height(::Subplot) must be implemented by each backend")
|
||||||
|
|
||||||
|
# # 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")
|
||||||
|
|
||||||
|
# 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
|
||||||
|
function plotarea_bbox(sp::Subplot)
|
||||||
|
crop(bbox(sp), BoundingBox(yaxis_width(sp), xaxis_height(sp), 1, 1 - title_height(sp)))
|
||||||
|
end
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
# subplot_bbox(subplot::Subplot) = error("subplot_bbox(::Subplot) must be implemented by each backend")
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
Base.size(layout::GridLayout) = size(layout.grid)
|
Base.size(layout::GridLayout) = size(layout.grid)
|
||||||
Base.length(layout::GridLayout) = length(layout.grid)
|
Base.length(layout::GridLayout) = length(layout.grid)
|
||||||
Base.getindex(layout::GridLayout, r::Int, c::Int) = layout.grid[r,c]
|
Base.getindex(layout::GridLayout, r::Int, c::Int) = layout.grid[r,c]
|
||||||
|
function Base.setindex!(layout::GridLayout, v, r::Int, c::Int)
|
||||||
|
layout.grid[r,c] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
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])
|
||||||
|
end
|
||||||
|
w
|
||||||
|
end
|
||||||
|
|
||||||
|
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])
|
||||||
|
end
|
||||||
|
h
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
# note: this should be called after all axis objects are updated to re-compute the
|
||||||
|
# bounding boxes for the layout tree
|
||||||
|
function update_bboxes!(layout::GridLayout) #, parent_bbox::BoundingBox = BoundingBox(0,0,1,1))
|
||||||
|
# initialize the free space (per child!)
|
||||||
|
nr, nc = size(layout)
|
||||||
|
freew, freeh = free_size(layout)
|
||||||
|
freew /= nc
|
||||||
|
freeh /= nr
|
||||||
|
|
||||||
|
# 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
|
||||||
|
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)
|
||||||
|
child_bbox = BoundingBox(l, b, l + usedw + freew, b + usedh + freeh)
|
||||||
|
|
||||||
|
# then compute the bounding box relative to the canvas, and cache it in the child object
|
||||||
|
bbox!(child, crop(bbox(layout), child_bbox))
|
||||||
|
|
||||||
|
# now recursively update the child
|
||||||
|
update_bboxes!(child)
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
nr, nc = size(layout)
|
||||||
|
subplots = Subplot[]
|
||||||
|
spmap = SubplotMap()
|
||||||
|
for r=1:nr, c=1:nc
|
||||||
|
sp = Subplot(backend(), parent=layout)
|
||||||
|
layout[r,c] = sp
|
||||||
|
push!(subplots, sp)
|
||||||
|
spmap[(r,c)] = sp
|
||||||
|
end
|
||||||
|
layout, subplots, spmap
|
||||||
|
end
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
# Base.start(layout::GridLayout) = 1
|
# Base.start(layout::GridLayout) = 1
|
||||||
# Base.done(layout::GridLayout, state) = state > length(layout)
|
# Base.done(layout::GridLayout, state) = state > length(layout)
|
||||||
|
|||||||
50
src/types.jl
50
src/types.jl
@ -35,12 +35,28 @@ end
|
|||||||
# Layouts
|
# Layouts
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
|
# wraps bounding box coords (percent of parent area)
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
abstract AbstractLayout
|
abstract AbstractLayout
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
# contains blank space
|
# contains blank space
|
||||||
immutable EmptyLayout <: AbstractLayout end
|
type EmptyLayout <: AbstractLayout
|
||||||
|
parent::AbstractLayout
|
||||||
|
bbox::BoundingBox
|
||||||
|
end
|
||||||
|
EmptyLayout(parent) = EmptyLayout(parent, BoundingBox(0,0,1,1))
|
||||||
|
|
||||||
# this is the parent of the top-level layout
|
# this is the parent of the top-level layout
|
||||||
immutable RootLayout <: AbstractLayout
|
immutable RootLayout <: AbstractLayout
|
||||||
@ -50,8 +66,9 @@ end
|
|||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
# a single subplot
|
# a single subplot
|
||||||
type Subplot <: AbstractLayout
|
type Subplot{T<:AbstractBackend} <: AbstractLayout
|
||||||
parent::AbstractLayout
|
parent::AbstractLayout
|
||||||
|
bbox::BoundingBox # the canvas area which is available to this subplot
|
||||||
attr::KW # args specific to this subplot
|
attr::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
|
||||||
@ -59,19 +76,40 @@ type Subplot <: AbstractLayout
|
|||||||
# Subplot(parent = RootLayout(); attr = KW())
|
# Subplot(parent = RootLayout(); attr = KW())
|
||||||
end
|
end
|
||||||
|
|
||||||
Subplot() = Subplot(RootLayout(), KW(), nothing)
|
function Subplot{T<:AbstractBackend}(::T; parent = RootLayout())
|
||||||
|
Subplot{T}(parent, BoundingBox(0,0,1,1), KW(), nothing)
|
||||||
|
end
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
# nested, gridded layout with optional size percentages
|
# nested, gridded layout with optional size percentages
|
||||||
immutable GridLayout <: AbstractLayout
|
type GridLayout <: AbstractLayout
|
||||||
parent::AbstractLayout
|
parent::AbstractLayout
|
||||||
|
bbox::BoundingBox
|
||||||
grid::Matrix{AbstractLayout} # Nested layouts. Each position is a AbstractLayout, which allows for arbitrary recursion
|
grid::Matrix{AbstractLayout} # Nested layouts. Each position is a AbstractLayout, which allows for arbitrary recursion
|
||||||
# widths::Vector{Float64}
|
widths::Vector{Float64}
|
||||||
# heights::Vector{Float64}
|
heights::Vector{Float64}
|
||||||
attr::KW
|
attr::KW
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function GridLayout(dims...;
|
||||||
|
parent = RootLayout(),
|
||||||
|
widths = ones(dims[2]),
|
||||||
|
heights = ones(dims[1]),
|
||||||
|
kw...)
|
||||||
|
grid = Matrix{AbstractLayout}(dims...)
|
||||||
|
layout = GridLayout(
|
||||||
|
parent,
|
||||||
|
BoundingBox(0,0,1,1),
|
||||||
|
grid,
|
||||||
|
convert(Vector{Float64}, widths),
|
||||||
|
convert(Vector{Float64}, heights),
|
||||||
|
KW(kw))
|
||||||
|
fill!(grid, EmptyLayout(layout))
|
||||||
|
layout
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
typealias SubplotMap Dict{Any, Subplot}
|
typealias SubplotMap Dict{Any, Subplot}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user