more layouts
This commit is contained in:
parent
b5f08838b3
commit
b08212e2f9
138
src/layouts.jl
138
src/layouts.jl
@ -1,4 +1,102 @@
|
|||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
# GridLayout
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
|
"Simple grid, indices are row-major."
|
||||||
|
immutable GridLayout <: SubplotLayout
|
||||||
|
nr::Int
|
||||||
|
nc::Int
|
||||||
|
end
|
||||||
|
|
||||||
|
Base.length(layout::GridLayout) = layout.nr * layout.nc
|
||||||
|
Base.start(layout::GridLayout) = 1
|
||||||
|
Base.done(layout::GridLayout, state) = state > length(layout)
|
||||||
|
function Base.next(layout::GridLayout, state)
|
||||||
|
r = div(state-1, layout.nc) + 1
|
||||||
|
c = mod1(state, layout.nc)
|
||||||
|
(r,c), state + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
nrows(layout::GridLayout) = layout.nr
|
||||||
|
ncols(layout::GridLayout) = layout.nc
|
||||||
|
ncols(layout::GridLayout, row::Int) = layout.nc
|
||||||
|
|
||||||
|
# get the plot index given row and column
|
||||||
|
Base.getindex(layout::GridLayout, r::Int, c::Int) = (r-1) * layout.nc + c
|
||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
# RowsLayout
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
|
"Number of plots per row"
|
||||||
|
immutable RowsLayout <: SubplotLayout
|
||||||
|
numplts::Int
|
||||||
|
rowcounts::AbstractVector{Int}
|
||||||
|
end
|
||||||
|
|
||||||
|
Base.length(layout::RowsLayout) = layout.numplts
|
||||||
|
Base.start(layout::RowsLayout) = 1
|
||||||
|
Base.done(layout::RowsLayout, state) = state > length(layout)
|
||||||
|
function Base.next(layout::RowsLayout, state)
|
||||||
|
r = 1
|
||||||
|
c = 0
|
||||||
|
for i = 1:state
|
||||||
|
c += 1
|
||||||
|
if c > layout.rowcounts[r]
|
||||||
|
r += 1
|
||||||
|
c = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
(r,c), state + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
nrows(layout::RowsLayout) = length(layout.rowcounts)
|
||||||
|
ncols(layout::RowsLayout, row::Int) = row < 1 ? 0 : (row > nrows(layout) ? 0 : layout.rowcounts[row])
|
||||||
|
|
||||||
|
# get the plot index given row and column
|
||||||
|
Base.getindex(layout::RowsLayout, r::Int, c::Int) = sum(layout.rowcounts[1:r-1]) + c
|
||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
# FlexLayout
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
|
"Flexible, nested layout with optional size percentages."
|
||||||
|
immutable FlexLayout <: SubplotLayout
|
||||||
|
n::Int
|
||||||
|
grid::Matrix # Nested layouts. Each position
|
||||||
|
# can be a plot index or another FlexLayout
|
||||||
|
widths::Vector{Float64}
|
||||||
|
heights::Vector{Float64}
|
||||||
|
end
|
||||||
|
|
||||||
|
typealias IntOrFlex Union{Int,FlexLayout}
|
||||||
|
|
||||||
|
Base.length(layout::FlexLayout) = layout.n
|
||||||
|
Base.start(layout::FlexLayout) = 1
|
||||||
|
Base.done(layout::FlexLayout, state) = state > length(layout)
|
||||||
|
function Base.next(layout::FlexLayout, state)
|
||||||
|
# TODO: change this method to return more info
|
||||||
|
# TODO: might consider multiple iterator types.. some backends might have an easier time row-by-row for example
|
||||||
|
error()
|
||||||
|
r = 1
|
||||||
|
c = 0
|
||||||
|
for i = 1:state
|
||||||
|
c += 1
|
||||||
|
if c > layout.rowcounts[r]
|
||||||
|
r += 1
|
||||||
|
c = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
(r,c), state + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
nrows(layout::FlexLayout) = size(layout.grid, 1)
|
||||||
|
ncols(layout::FlexLayout, row::Int) = size(layout.grid, 2)
|
||||||
|
|
||||||
|
# get the plot index given row and column
|
||||||
|
Base.getindex(layout::FlexLayout, r::Int, c::Int) = layout.grid[r,c]
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
# we're taking in a nested structure of some kind... parse it out and build a FlexLayout
|
# we're taking in a nested structure of some kind... parse it out and build a FlexLayout
|
||||||
@ -78,43 +176,3 @@ function subplotlayout(numplts::Int, nr::Int, nc::Int)
|
|||||||
|
|
||||||
RowsLayout(numplts, rowcounts)
|
RowsLayout(numplts, rowcounts)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Base.length(layout::RowsLayout) = layout.numplts
|
|
||||||
Base.start(layout::RowsLayout) = 1
|
|
||||||
Base.done(layout::RowsLayout, state) = state > length(layout)
|
|
||||||
function Base.next(layout::RowsLayout, state)
|
|
||||||
r = 1
|
|
||||||
c = 0
|
|
||||||
for i = 1:state
|
|
||||||
c += 1
|
|
||||||
if c > layout.rowcounts[r]
|
|
||||||
r += 1
|
|
||||||
c = 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
(r,c), state + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
nrows(layout::RowsLayout) = length(layout.rowcounts)
|
|
||||||
ncols(layout::RowsLayout, row::Int) = row < 1 ? 0 : (row > nrows(layout) ? 0 : layout.rowcounts[row])
|
|
||||||
|
|
||||||
# get the plot index given row and column
|
|
||||||
Base.getindex(layout::RowsLayout, r::Int, c::Int) = sum(layout.rowcounts[1:r-1]) + c
|
|
||||||
|
|
||||||
Base.length(layout::GridLayout) = layout.nr * layout.nc
|
|
||||||
Base.start(layout::GridLayout) = 1
|
|
||||||
Base.done(layout::GridLayout, state) = state > length(layout)
|
|
||||||
function Base.next(layout::GridLayout, state)
|
|
||||||
r = div(state-1, layout.nc) + 1
|
|
||||||
c = mod1(state, layout.nc)
|
|
||||||
(r,c), state + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
nrows(layout::GridLayout) = layout.nr
|
|
||||||
ncols(layout::GridLayout) = layout.nc
|
|
||||||
ncols(layout::GridLayout, row::Int) = layout.nc
|
|
||||||
|
|
||||||
# get the plot index given row and column
|
|
||||||
Base.getindex(layout::GridLayout, r::Int, c::Int) = (r-1) * layout.nc + c
|
|
||||||
|
|||||||
@ -1,53 +1,18 @@
|
|||||||
|
|
||||||
Base.getindex(subplt::Subplot, args...) = subplt.plts[subplt.layout[args...]]
|
|
||||||
|
|
||||||
# handle "linking" the subplot axes together
|
|
||||||
# each backend should implement the _remove_axis and _expand_limits methods
|
|
||||||
function link_axis(subplt::Subplot, isx::Bool)
|
|
||||||
|
|
||||||
# collect the list of plots and the expanded limits for those plots that should be linked on this axis
|
|
||||||
includedPlots = Any[]
|
|
||||||
# lims = [Inf, -Inf]
|
|
||||||
lims = Dict{Int,Any}() # maps column to xlim
|
|
||||||
for (i,(r,c)) in enumerate(subplt.layout)
|
|
||||||
|
|
||||||
# shouldlink will be a bool or nothing. if nothing, then use linkx/y (which is true if we get to this code)
|
|
||||||
shouldlink = subplt.linkfunc(r,c)[isx ? 1 : 2]
|
|
||||||
if shouldlink == nothing || shouldlink
|
|
||||||
plt = subplt.plts[i]
|
|
||||||
|
|
||||||
# if we don't have this
|
|
||||||
k = isx ? c : r
|
|
||||||
if (firstone = !haskey(lims, k))
|
|
||||||
lims[k] = [Inf, -Inf]
|
|
||||||
end
|
|
||||||
|
|
||||||
isinner = (isx && r < nrows(subplt.layout)) || (!isx && !firstone)
|
|
||||||
push!(includedPlots, (plt, isinner, k))
|
|
||||||
|
|
||||||
_expand_limits(lims[k], plt, isx)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
# do the axis adjustments
|
|
||||||
for (plt, isinner, k) in includedPlots
|
|
||||||
if isinner
|
|
||||||
_remove_axis(plt, isx)
|
|
||||||
end
|
|
||||||
(isx ? xlims! : ylims!)(plt, lims[k]...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
Base.string(subplt::Subplot) = "Subplot{$(subplt.backend) p=$(subplt.p) n=$(subplt.n)}"
|
Base.string(subplt::Subplot) = "Subplot{$(subplt.backend) p=$(subplt.p) n=$(subplt.n)}"
|
||||||
Base.print(io::IO, subplt::Subplot) = print(io, string(subplt))
|
Base.print(io::IO, subplt::Subplot) = print(io, string(subplt))
|
||||||
Base.show(io::IO, subplt::Subplot) = print(io, string(subplt))
|
Base.show(io::IO, subplt::Subplot) = print(io, string(subplt))
|
||||||
|
|
||||||
|
function Base.copy(subplt::Subplot)
|
||||||
|
subplot(subplt.plts, subplt.layout, subplt.plotargs)
|
||||||
|
end
|
||||||
|
|
||||||
|
Base.getindex(subplt::Subplot, args...) = subplt.plts[subplt.layout[args...]]
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------
|
||||||
|
|
||||||
getplot(subplt::Subplot, idx::Int = subplt.n) = subplt.plts[mod1(idx, subplt.p)]
|
getplot(subplt::Subplot, idx::Int = subplt.n) = subplt.plts[mod1(idx, subplt.p)]
|
||||||
getplotargs(subplt::Subplot, idx::Int) = getplot(subplt, idx).plotargs
|
getplotargs(subplt::Subplot, idx::Int) = getplot(subplt, idx).plotargs
|
||||||
convertSeriesIndex(subplt::Subplot, n::Int) = ceil(Int, n / subplt.p)
|
convertSeriesIndex(subplt::Subplot, n::Int) = ceil(Int, n / subplt.p)
|
||||||
@ -297,10 +262,42 @@ function _add_series_subplot(plt::Plot, args...; kw...)
|
|||||||
warnOnUnsupportedScales(plt.backend, d)
|
warnOnUnsupportedScales(plt.backend, d)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
||||||
function Base.copy(subplt::Subplot)
|
# handle "linking" the subplot axes together
|
||||||
subplot(subplt.plts, subplt.layout, subplt.plotargs)
|
# each backend should implement the _remove_axis and _expand_limits methods
|
||||||
|
function link_axis(subplt::Subplot, isx::Bool)
|
||||||
|
|
||||||
|
# collect the list of plots and the expanded limits for those plots that should be linked on this axis
|
||||||
|
includedPlots = Any[]
|
||||||
|
# lims = [Inf, -Inf]
|
||||||
|
lims = Dict{Int,Any}() # maps column to xlim
|
||||||
|
for (i,(r,c)) in enumerate(subplt.layout)
|
||||||
|
|
||||||
|
# shouldlink will be a bool or nothing. if nothing, then use linkx/y (which is true if we get to this code)
|
||||||
|
shouldlink = subplt.linkfunc(r,c)[isx ? 1 : 2]
|
||||||
|
if shouldlink == nothing || shouldlink
|
||||||
|
plt = subplt.plts[i]
|
||||||
|
|
||||||
|
# if we don't have this
|
||||||
|
k = isx ? c : r
|
||||||
|
if (firstone = !haskey(lims, k))
|
||||||
|
lims[k] = [Inf, -Inf]
|
||||||
|
end
|
||||||
|
|
||||||
|
isinner = (isx && r < nrows(subplt.layout)) || (!isx && !firstone)
|
||||||
|
push!(includedPlots, (plt, isinner, k))
|
||||||
|
|
||||||
|
_expand_limits(lims[k], plt, isx)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
# do the axis adjustments
|
||||||
|
for (plt, isinner, k) in includedPlots
|
||||||
|
if isinner
|
||||||
|
_remove_axis(plt, isx)
|
||||||
|
end
|
||||||
|
(isx ? xlims! : ylims!)(plt, lims[k]...)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
31
src/types.jl
31
src/types.jl
@ -20,40 +20,11 @@ type Plot{T<:AbstractBackend} <: AbstractPlot{T}
|
|||||||
end
|
end
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
# Layouts
|
# Layout
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
abstract SubplotLayout
|
abstract SubplotLayout
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
|
||||||
|
|
||||||
"Simple grid, indices are row-major."
|
|
||||||
immutable GridLayout <: SubplotLayout
|
|
||||||
nr::Int
|
|
||||||
nc::Int
|
|
||||||
end
|
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
|
||||||
|
|
||||||
"Number of plots per row"
|
|
||||||
immutable RowsLayout <: SubplotLayout
|
|
||||||
numplts::Int
|
|
||||||
rowcounts::AbstractVector{Int}
|
|
||||||
end
|
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
|
||||||
|
|
||||||
"Flexible, nested layout with optional size percentages."
|
|
||||||
immutable FlexLayout <: SubplotLayout
|
|
||||||
n::Int
|
|
||||||
grid::Matrix # Nested layouts. Each position
|
|
||||||
# can be a plot index or another FlexLayout
|
|
||||||
widths::Vector{Float64}
|
|
||||||
heights::Vector{Float64}
|
|
||||||
end
|
|
||||||
|
|
||||||
typealias IntOrFlex Union{Int,FlexLayout}
|
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
# Subplot
|
# Subplot
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user