layout macro; attr rename; getindex; fixes and cleanup
This commit is contained in:
parent
bfc3fc1dec
commit
0d96c49f4a
@ -17,11 +17,14 @@ export
|
|||||||
AbstractLayout,
|
AbstractLayout,
|
||||||
GridLayout,
|
GridLayout,
|
||||||
EmptyLayout,
|
EmptyLayout,
|
||||||
|
@layout,
|
||||||
# RowsLayout,
|
# RowsLayout,
|
||||||
# FlexLayout,
|
# FlexLayout,
|
||||||
AVec,
|
AVec,
|
||||||
AMat,
|
AMat,
|
||||||
KW,
|
KW,
|
||||||
|
attr,
|
||||||
|
attr!,
|
||||||
|
|
||||||
wrap,
|
wrap,
|
||||||
set_theme,
|
set_theme,
|
||||||
|
|||||||
@ -234,7 +234,7 @@ for letter in (:x,:y,:z)
|
|||||||
_axis_defaults_byletter[symbol(letter,k)] = nothing
|
_axis_defaults_byletter[symbol(letter,k)] = nothing
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@show _axis_defaults
|
# @show _axis_defaults
|
||||||
# for letter in (:x, :y, :z)
|
# for letter in (:x, :y, :z)
|
||||||
# for (k,v) in _axis_defaults
|
# for (k,v) in _axis_defaults
|
||||||
# _axis_defaults[symbol(letter,k)] = v
|
# _axis_defaults[symbol(letter,k)] = v
|
||||||
@ -922,7 +922,7 @@ 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)
|
function _update_subplot_args(plt::Plot, sp::Subplot, d_in::KW, subplot_index::Integer)
|
||||||
pargs = plt.plotargs
|
pargs = plt.plotargs
|
||||||
spargs = sp.subplotargs
|
spargs = sp.attr
|
||||||
# @show subplot_index, sp
|
# @show subplot_index, sp
|
||||||
for (k,v) in _subplot_defaults
|
for (k,v) in _subplot_defaults
|
||||||
slice_arg!(d_in, spargs, k, v, subplot_index)
|
slice_arg!(d_in, spargs, k, v, subplot_index)
|
||||||
|
|||||||
@ -293,7 +293,7 @@ end
|
|||||||
function py_bbox_axis(ax, letter)
|
function py_bbox_axis(ax, letter)
|
||||||
ticks = py_bbox_ticks(ax, letter)
|
ticks = py_bbox_ticks(ax, letter)
|
||||||
labels = py_bbox_axislabel(ax, letter)
|
labels = py_bbox_axislabel(ax, letter)
|
||||||
letter == "x" && @show ticks labels ticks+labels
|
# letter == "x" && @show ticks labels ticks+labels
|
||||||
ticks + labels
|
ticks + labels
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -395,14 +395,14 @@ end
|
|||||||
function _initialize_subplot(plt::Plot{PyPlotBackend}, sp::Subplot{PyPlotBackend})
|
function _initialize_subplot(plt::Plot{PyPlotBackend}, sp::Subplot{PyPlotBackend})
|
||||||
fig = plt.o
|
fig = plt.o
|
||||||
# add a new axis, and force it to create a new one by setting a distinct label
|
# add a new axis, and force it to create a new one by setting a distinct label
|
||||||
proj = sp.subplotargs[:projection]
|
proj = sp.attr[:projection]
|
||||||
ax = fig[:add_axes](
|
ax = fig[:add_axes](
|
||||||
[0,0,1,1],
|
[0,0,1,1],
|
||||||
label = string(gensym()),
|
label = string(gensym()),
|
||||||
projection = (proj in (nothing,:none) ? nothing : string(proj))
|
projection = (proj in (nothing,:none) ? nothing : string(proj))
|
||||||
)
|
)
|
||||||
# projection =
|
# projection =
|
||||||
# ax = fig[:add_subplot](111, projection = _py_projections[sp.subplotargs[:projection]])
|
# ax = fig[:add_subplot](111, projection = _py_projections[sp.attr[:projection]])
|
||||||
# for axis in (:xaxis, :yaxis)
|
# for axis in (:xaxis, :yaxis)
|
||||||
# ax[axis][:_autolabelpos] = false
|
# ax[axis][:_autolabelpos] = false
|
||||||
# end
|
# end
|
||||||
@ -948,7 +948,7 @@ function _add_series(plt::Plot{PyPlotBackend}, series::Series)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# this sets the bg color inside the grid
|
# this sets the bg color inside the grid
|
||||||
ax[:set_axis_bgcolor](getPyPlotColor(d[:subplot].subplotargs[:background_color_inside]))
|
ax[:set_axis_bgcolor](getPyPlotColor(d[:subplot].attr[:background_color_inside]))
|
||||||
|
|
||||||
# handle area filling
|
# handle area filling
|
||||||
fillrange = d[:fillrange]
|
fillrange = d[:fillrange]
|
||||||
@ -1137,7 +1137,7 @@ function _update_plot(plt::Plot{PyPlotBackend}, d::KW)
|
|||||||
# figorax = plt.o
|
# figorax = plt.o
|
||||||
# ax = getLeftAxis(figorax)
|
# ax = getLeftAxis(figorax)
|
||||||
for sp in plt.subplots
|
for sp in plt.subplots
|
||||||
spargs = sp.subplotargs
|
spargs = sp.attr
|
||||||
ax = getAxis(sp)
|
ax = getAxis(sp)
|
||||||
# ticksz = get(d, :tickfont, plt.plotargs[:tickfont]).pointsize
|
# ticksz = get(d, :tickfont, plt.plotargs[:tickfont]).pointsize
|
||||||
# guidesz = get(d, :guidefont, spargs[:guidefont]).pointsize
|
# guidesz = get(d, :guidefont, spargs[:guidefont]).pointsize
|
||||||
@ -1348,7 +1348,7 @@ const _pyplot_legend_pos = KW(
|
|||||||
# function addPyPlotLegend(plt::Plot)
|
# function addPyPlotLegend(plt::Plot)
|
||||||
# function addPyPlotLegend(plt::Plot, ax)
|
# function addPyPlotLegend(plt::Plot, ax)
|
||||||
function addPyPlotLegend(plt::Plot, sp::Subplot, ax)
|
function addPyPlotLegend(plt::Plot, sp::Subplot, ax)
|
||||||
leg = sp.subplotargs[:legend]
|
leg = sp.attr[:legend]
|
||||||
if leg != :none
|
if leg != :none
|
||||||
# gotta do this to ensure both axes are included
|
# gotta do this to ensure both axes are included
|
||||||
labels = []
|
labels = []
|
||||||
@ -1376,19 +1376,19 @@ function addPyPlotLegend(plt::Plot, sp::Subplot, ax)
|
|||||||
labels, #[d[:label] for d in args],
|
labels, #[d[:label] for d in args],
|
||||||
loc = get(_pyplot_legend_pos, leg, "best"),
|
loc = get(_pyplot_legend_pos, leg, "best"),
|
||||||
scatterpoints = 1,
|
scatterpoints = 1,
|
||||||
fontsize = sp.subplotargs[:legendfont].pointsize
|
fontsize = sp.attr[:legendfont].pointsize
|
||||||
# framealpha = 0.6
|
# framealpha = 0.6
|
||||||
)
|
)
|
||||||
leg[:set_zorder](1000)
|
leg[:set_zorder](1000)
|
||||||
|
|
||||||
fgcolor = getPyPlotColor(sp.subplotargs[:foreground_color_legend])
|
fgcolor = getPyPlotColor(sp.attr[:foreground_color_legend])
|
||||||
for txt in leg[:get_texts]()
|
for txt in leg[:get_texts]()
|
||||||
PyPlot.plt[:setp](txt, color = fgcolor)
|
PyPlot.plt[:setp](txt, color = fgcolor)
|
||||||
end
|
end
|
||||||
|
|
||||||
# set some legend properties
|
# set some legend properties
|
||||||
frame = leg[:get_frame]()
|
frame = leg[:get_frame]()
|
||||||
frame[:set_facecolor](getPyPlotColor(sp.subplotargs[:background_color_legend]))
|
frame[:set_facecolor](getPyPlotColor(sp.attr[:background_color_legend]))
|
||||||
frame[:set_edgecolor](fgcolor)
|
frame[:set_edgecolor](fgcolor)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1402,7 +1402,7 @@ function finalizePlot(plt::Plot{PyPlotBackend})
|
|||||||
ax = getAxis(sp)
|
ax = getAxis(sp)
|
||||||
addPyPlotLegend(plt, sp, ax)
|
addPyPlotLegend(plt, sp, ax)
|
||||||
for asym in (:xaxis, :yaxis, :zaxis)
|
for asym in (:xaxis, :yaxis, :zaxis)
|
||||||
updateAxisColors(ax, sp.subplotargs[asym])
|
updateAxisColors(ax, sp.attr[asym])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
drawfig(plt.o)
|
drawfig(plt.o)
|
||||||
|
|||||||
22
src/plot.jl
22
src/plot.jl
@ -46,7 +46,7 @@ function plot(args...; kw...)
|
|||||||
pkg = backend()
|
pkg = backend()
|
||||||
d = KW(kw)
|
d = KW(kw)
|
||||||
preprocessArgs!(d)
|
preprocessArgs!(d)
|
||||||
DD(d,"pre")
|
# DD(d,"pre")
|
||||||
|
|
||||||
# create an empty Plot, update the args using the inputs, then pass it
|
# create an empty Plot, update the args using the inputs, then pass it
|
||||||
# to the backend to finish backend-specific initialization
|
# to the backend to finish backend-specific initialization
|
||||||
@ -61,7 +61,7 @@ function plot(args...; kw...)
|
|||||||
# update the subplot/axis args from inputs, then pass to backend to init further
|
# update the subplot/axis args from inputs, then pass to backend to init further
|
||||||
sp.plt = plt
|
sp.plt = plt
|
||||||
_update_subplot_args(plt, sp, copy(d), idx)
|
_update_subplot_args(plt, sp, copy(d), idx)
|
||||||
# DD(sp.subplotargs[:xaxis].d,"$idx")
|
# DD(sp.attr[:xaxis].d,"$idx")
|
||||||
|
|
||||||
# TODO: i'd like to know what projection we're using by this point... can I push this off until later??
|
# TODO: i'd like to know what projection we're using by this point... can I push this off until later??
|
||||||
# I won't easily be able to auto-determine what series types are coming...
|
# I won't easily be able to auto-determine what series types are coming...
|
||||||
@ -167,7 +167,7 @@ function _apply_series_recipe(plt::Plot, d::KW)
|
|||||||
# adjust extrema and discrete info
|
# adjust extrema and discrete info
|
||||||
for s in (:x, :y, :z)
|
for s in (:x, :y, :z)
|
||||||
data = d[s]
|
data = d[s]
|
||||||
axis = sp.subplotargs[symbol(s, "axis")]
|
axis = sp.attr[symbol(s, "axis")]
|
||||||
if eltype(data) <: Number
|
if eltype(data) <: Number
|
||||||
expand_extrema!(axis, data)
|
expand_extrema!(axis, data)
|
||||||
else
|
else
|
||||||
@ -330,18 +330,20 @@ 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, :auto), i)
|
sp = get(kw, :subplot, :auto)
|
||||||
if sp == :auto
|
sp = if sp == :auto
|
||||||
sp = 1 # TODO: something useful
|
mod1(i,length(plt.subplots))
|
||||||
|
else
|
||||||
|
slice_arg(sp, i)
|
||||||
end
|
end
|
||||||
sp = kw[:subplot] = get_subplot(plt, sp)
|
sp = kw[:subplot] = get_subplot(plt, sp)
|
||||||
idx = get_subplot_index(plt, sp)
|
idx = get_subplot_index(plt, sp)
|
||||||
|
|
||||||
# we update subplot args in case something like the color palatte is part of the recipe
|
# we update subplot args in case something like the color palatte is part of the recipe
|
||||||
# DD(sp.subplotargs[:xaxis].d, "before USA $i")
|
# DD(sp.attr[:xaxis].d, "before USA $i")
|
||||||
# DD(kw, "kw")
|
# DD(kw, "kw")
|
||||||
_update_subplot_args(plt, sp, kw, idx)
|
_update_subplot_args(plt, sp, kw, idx)
|
||||||
# DD(sp.subplotargs[:xaxis].d, "after USA $i")
|
# DD(sp.attr[:xaxis].d, "after USA $i")
|
||||||
|
|
||||||
# set default values, select from attribute cycles, and generally set the final attributes
|
# set default values, select from attribute cycles, and generally set the final attributes
|
||||||
_add_defaults!(kw, plt, sp, i)
|
_add_defaults!(kw, plt, sp, i)
|
||||||
@ -355,9 +357,9 @@ function _plot!(plt::Plot, d::KW, args...)
|
|||||||
# For example, a histogram is just a bar plot with binned data, a bar plot is really a filled step plot,
|
# For example, a histogram is just a bar plot with binned data, a bar plot is really a filled step plot,
|
||||||
# and a step plot is really just a path. So any backend that supports drawing a path will implicitly
|
# and a step plot is really just a path. So any backend that supports drawing a path will implicitly
|
||||||
# be able to support step, bar, and histogram plots (and any recipes that use those components).
|
# be able to support step, bar, and histogram plots (and any recipes that use those components).
|
||||||
# DD(sp.subplotargs[:xaxis].d, "before $i")
|
# DD(sp.attr[:xaxis].d, "before $i")
|
||||||
_apply_series_recipe(plt, kw)
|
_apply_series_recipe(plt, kw)
|
||||||
# DD(sp.subplotargs[:xaxis].d, "after $i")
|
# DD(sp.attr[:xaxis].d, "after $i")
|
||||||
end
|
end
|
||||||
|
|
||||||
# now that we're done adding all the series, add the annotations
|
# now that we're done adding all the series, add the annotations
|
||||||
|
|||||||
@ -27,7 +27,7 @@ function _add_defaults!(d::KW, plt::Plot, sp::Subplot, commandIndex::Int)
|
|||||||
aliasesAndAutopick(d, :markershape, _markerAliases, supportedMarkers(pkg), plotIndex)
|
aliasesAndAutopick(d, :markershape, _markerAliases, supportedMarkers(pkg), plotIndex)
|
||||||
|
|
||||||
# update color
|
# update color
|
||||||
d[:seriescolor] = getSeriesRGBColor(d[:seriescolor], sp.subplotargs, plotIndex)
|
d[:seriescolor] = getSeriesRGBColor(d[:seriescolor], sp.attr, plotIndex)
|
||||||
|
|
||||||
# update colors
|
# update colors
|
||||||
for csym in (:linecolor, :markercolor, :fillcolor)
|
for csym in (:linecolor, :markercolor, :fillcolor)
|
||||||
@ -38,16 +38,16 @@ function _add_defaults!(d::KW, plt::Plot, sp::Subplot, commandIndex::Int)
|
|||||||
d[:seriescolor]
|
d[:seriescolor]
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
getSeriesRGBColor(d[csym], sp.subplotargs, plotIndex)
|
getSeriesRGBColor(d[csym], sp.attr, plotIndex)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# update markerstrokecolor
|
# update markerstrokecolor
|
||||||
c = d[:markerstrokecolor]
|
c = d[:markerstrokecolor]
|
||||||
c = if c == :match
|
c = if c == :match
|
||||||
sp.subplotargs[:foreground_color_subplot]
|
sp.attr[:foreground_color_subplot]
|
||||||
else
|
else
|
||||||
getSeriesRGBColor(c, sp.subplotargs, plotIndex)
|
getSeriesRGBColor(c, sp.attr, plotIndex)
|
||||||
end
|
end
|
||||||
d[:markerstrokecolor] = c
|
d[:markerstrokecolor] = c
|
||||||
|
|
||||||
|
|||||||
@ -125,29 +125,29 @@ function update_child_bboxes!(layout::GridLayout)
|
|||||||
nr, nc = size(layout)
|
nr, nc = size(layout)
|
||||||
|
|
||||||
# create a matrix for each minimum padding direction
|
# create a matrix for each minimum padding direction
|
||||||
minpad_left = map(min_padding_left, layout.grid)
|
minpad_left = map(min_padding_left, layout.grid)
|
||||||
minpad_top = map(min_padding_top, layout.grid)
|
minpad_top = map(min_padding_top, layout.grid)
|
||||||
minpad_right = map(min_padding_right, layout.grid)
|
minpad_right = map(min_padding_right, layout.grid)
|
||||||
minpad_bottom = map(min_padding_bottom, layout.grid)
|
minpad_bottom = map(min_padding_bottom, layout.grid)
|
||||||
# @show minpad_left minpad_top minpad_right minpad_bottom
|
# @show minpad_left minpad_top minpad_right minpad_bottom
|
||||||
|
|
||||||
# get the max horizontal (left and right) padding over columns,
|
# get the max horizontal (left and right) padding over columns,
|
||||||
# and max vertical (bottom and top) padding over rows
|
# and max vertical (bottom and top) padding over rows
|
||||||
# TODO: add extra padding here
|
# TODO: add extra padding here
|
||||||
pad_left = maximum(minpad_left, 1)
|
pad_left = maximum(minpad_left, 1)
|
||||||
pad_top = maximum(minpad_top, 2)
|
pad_top = maximum(minpad_top, 2)
|
||||||
pad_right = maximum(minpad_right, 1)
|
pad_right = maximum(minpad_right, 1)
|
||||||
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
|
||||||
|
|
||||||
# scale this up to the total padding in each direction
|
# scale this up to the total padding in each direction
|
||||||
total_pad_horizontal = (pad_left + pad_right) .* nc
|
total_pad_horizontal = (pad_left + pad_right) .* nc
|
||||||
total_pad_vertical = (pad_top + pad_bottom) .* nr
|
total_pad_vertical = (pad_top + pad_bottom) .* nr
|
||||||
# @show total_pad_horizontal total_pad_vertical
|
# @show total_pad_horizontal total_pad_vertical
|
||||||
|
|
||||||
# now we can compute the total plot area in each direction
|
# now we can compute the total plot area in each direction
|
||||||
total_plotarea_horizontal = width(layout) - total_pad_horizontal
|
total_plotarea_horizontal = width(layout) - total_pad_horizontal
|
||||||
total_plotarea_vertical = height(layout) - total_pad_vertical
|
total_plotarea_vertical = height(layout) - total_pad_vertical
|
||||||
# @show total_plotarea_horizontal total_plotarea_vertical
|
# @show total_plotarea_horizontal total_plotarea_vertical
|
||||||
|
|
||||||
# normalize widths/heights so they sum to 1
|
# normalize widths/heights so they sum to 1
|
||||||
@ -161,19 +161,19 @@ function update_child_bboxes!(layout::GridLayout)
|
|||||||
|
|
||||||
# get the top-left corner of this child
|
# get the top-left corner of this child
|
||||||
child_left = (c == 1 ? 0mm : right(layout[r, c-1].bbox))
|
child_left = (c == 1 ? 0mm : right(layout[r, c-1].bbox))
|
||||||
child_top = (r == 1 ? 0mm : bottom(layout[r-1, c].bbox))
|
child_top = (r == 1 ? 0mm : bottom(layout[r-1, c].bbox))
|
||||||
|
|
||||||
# compute plot area
|
# compute plot area
|
||||||
plotarea_left = child_left + pad_left[c]
|
plotarea_left = child_left + pad_left[c]
|
||||||
plotarea_top = child_top + pad_top[r]
|
plotarea_top = child_top + pad_top[r]
|
||||||
plotarea_width = total_plotarea_horizontal[c] * layout.widths[c] / denom_w
|
plotarea_width = total_plotarea_horizontal[c] * layout.widths[c] / denom_w
|
||||||
plotarea_height = total_plotarea_vertical[r] * layout.heights[r] / denom_h
|
plotarea_height = total_plotarea_vertical[r] * layout.heights[r] / denom_h
|
||||||
child_plotarea = BoundingBox(plotarea_left, plotarea_top, plotarea_width, plotarea_height)
|
child_plotarea = BoundingBox(plotarea_left, plotarea_top, plotarea_width, plotarea_height)
|
||||||
|
|
||||||
# compute child bbox
|
# compute child bbox
|
||||||
child_width = pad_left[c] + plotarea_width + pad_right[c]
|
child_width = pad_left[c] + plotarea_width + pad_right[c]
|
||||||
child_height = pad_top[r] + plotarea_height + pad_bottom[r]
|
child_height = pad_top[r] + plotarea_height + pad_bottom[r]
|
||||||
child_bbox = BoundingBox(child_left, child_top, child_width, child_height)
|
child_bbox = BoundingBox(child_left, child_top, child_width, child_height)
|
||||||
# @show (r,c) child_plotarea child_bbox
|
# @show (r,c) child_plotarea child_bbox
|
||||||
|
|
||||||
# the bounding boxes are currently relative to the parent, but we need them relative to the canvas
|
# the bounding boxes are currently relative to the parent, but we need them relative to the canvas
|
||||||
@ -308,25 +308,29 @@ function build_layout(layout::GridLayout, n::Integer)
|
|||||||
nr, nc = size(layout)
|
nr, nc = size(layout)
|
||||||
subplots = Subplot[]
|
subplots = Subplot[]
|
||||||
spmap = SubplotMap()
|
spmap = SubplotMap()
|
||||||
i = 1
|
i = 0
|
||||||
for r=1:nr, c=1:nc
|
for r=1:nr, c=1:nc
|
||||||
i > n && break # only add n subplots
|
|
||||||
l = layout[r,c]
|
l = layout[r,c]
|
||||||
if isa(l, EmptyLayout)
|
if isa(l, EmptyLayout)
|
||||||
sp = Subplot(backend(), parent=layout)
|
sp = Subplot(backend(), parent=layout)
|
||||||
layout[r,c] = sp
|
layout[r,c] = sp
|
||||||
push!(subplots, sp)
|
push!(subplots, sp)
|
||||||
spmap[length(subplots)] = sp
|
spmap[attr(l,:label)] = sp
|
||||||
|
if hasattr(l,:width)
|
||||||
|
layout.widths[c] = attr(l,:width)
|
||||||
|
end
|
||||||
|
if hasattr(l,:height)
|
||||||
|
layout.heights[r] = attr(l,:height)
|
||||||
|
end
|
||||||
i += 1
|
i += 1
|
||||||
elseif isa(l, GridLayout)
|
elseif isa(l, GridLayout)
|
||||||
# sub-grid
|
# sub-grid
|
||||||
l, sps, m = build_layout(l)
|
l, sps, m = build_layout(l, n-i)
|
||||||
append!(subplots, sps)
|
append!(subplots, sps)
|
||||||
for (k,v) in m
|
merge!(spmap, m)
|
||||||
spmap[k+length(subplots)] = v
|
|
||||||
end
|
|
||||||
i += length(sps)
|
i += length(sps)
|
||||||
end
|
end
|
||||||
|
i >= n && break # only add n subplots
|
||||||
end
|
end
|
||||||
layout, subplots, spmap
|
layout, subplots, spmap
|
||||||
end
|
end
|
||||||
@ -361,6 +365,37 @@ get_subplot_index(plt::Plot, idx::Integer) = idx
|
|||||||
get_subplot_index(plt::Plot, sp::Subplot) = findfirst(sp->sp === plt.subplots[2], plt.subplots)
|
get_subplot_index(plt::Plot, sp::Subplot) = findfirst(sp->sp === plt.subplots[2], plt.subplots)
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
function create_grid(expr::Expr)
|
||||||
|
cellsym = gensym(:cell)
|
||||||
|
constructor = if expr.head == :vcat
|
||||||
|
:(let
|
||||||
|
$cellsym = GridLayout($(length(expr.args)), 1)
|
||||||
|
$([:($cellsym[$i,1] = $(create_grid(expr.args[i]))) for i=1:length(expr.args)]...)
|
||||||
|
$cellsym
|
||||||
|
end)
|
||||||
|
elseif expr.head in (:hcat,:row)
|
||||||
|
:(let
|
||||||
|
$cellsym = GridLayout(1, $(length(expr.args)))
|
||||||
|
$([:($cellsym[1,$i] = $(create_grid(expr.args[i]))) for i=1:length(expr.args)]...)
|
||||||
|
$cellsym
|
||||||
|
end)
|
||||||
|
|
||||||
|
elseif expr.head == :curly
|
||||||
|
length(expr.args) == 3 || error("Should be width and height in curly. Got: ", expr.args)
|
||||||
|
s,w,h = expr.args
|
||||||
|
:(EmptyLayout(label = $(QuoteNode(s)), width = $w, height = $h))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function create_grid(s::Symbol)
|
||||||
|
:(EmptyLayout(label = $(QuoteNode(s))))
|
||||||
|
end
|
||||||
|
|
||||||
|
macro layout(mat::Expr)
|
||||||
|
create_grid(mat)
|
||||||
|
end
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
# Base.start(layout::GridLayout) = 1
|
# Base.start(layout::GridLayout) = 1
|
||||||
|
|||||||
29
src/types.jl
29
src/types.jl
@ -99,11 +99,6 @@ function Base.(:+)(bb1::BoundingBox, bb2::BoundingBox)
|
|||||||
ispositive(width(bb2)) || return bb1
|
ispositive(width(bb2)) || return bb1
|
||||||
ispositive(height(bb2)) || return bb1
|
ispositive(height(bb2)) || return bb1
|
||||||
|
|
||||||
# if width(bb1) <= 0mm || height(bb1) <= 0mm
|
|
||||||
# return bb2
|
|
||||||
# elseif width(bb2) <= 0mm || height(bb2) <= 0mm
|
|
||||||
# return bb1
|
|
||||||
# end
|
|
||||||
l = min(left(bb1), left(bb2))
|
l = min(left(bb1), left(bb2))
|
||||||
t = min(top(bb1), top(bb2))
|
t = min(top(bb1), top(bb2))
|
||||||
r = max(right(bb1), right(bb2))
|
r = max(right(bb1), right(bb2))
|
||||||
@ -114,10 +109,6 @@ 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
|
||||||
# is relative to the parent
|
# is relative to the parent
|
||||||
function crop(parent::BoundingBox, child::BoundingBox)
|
function crop(parent::BoundingBox, child::BoundingBox)
|
||||||
# l = left(parent) + width(parent) * left(child)
|
|
||||||
# b = bottom(parent) + height(parent) * bottom(child)
|
|
||||||
# w = width(parent) * width(child)
|
|
||||||
# h = height(parent) * height(child)
|
|
||||||
l = left(parent) + left(child)
|
l = left(parent) + left(child)
|
||||||
t = top(parent) + top(child)
|
t = top(parent) + top(child)
|
||||||
w = width(child)
|
w = width(child)
|
||||||
@ -137,14 +128,20 @@ width(layout::AbstractLayout) = width(layout.bbox)
|
|||||||
height(layout::AbstractLayout) = height(layout.bbox)
|
height(layout::AbstractLayout) = height(layout.bbox)
|
||||||
plotarea!(layout::AbstractLayout, bbox::BoundingBox) = nothing
|
plotarea!(layout::AbstractLayout, bbox::BoundingBox) = nothing
|
||||||
|
|
||||||
|
attr(layout::AbstractLayout, k::Symbol) = layout.attr[k]
|
||||||
|
attr!(layout::AbstractLayout, v, k::Symbol) = (layout.attr[k] = v)
|
||||||
|
hasattr(layout::AbstractLayout, k::Symbol) = haskey(layout.attr, k)
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
# contains blank space
|
# contains blank space
|
||||||
type EmptyLayout <: AbstractLayout
|
type EmptyLayout <: AbstractLayout
|
||||||
parent::AbstractLayout
|
parent::AbstractLayout
|
||||||
bbox::BoundingBox
|
bbox::BoundingBox
|
||||||
|
attr::KW # store label, width, and height for initialization
|
||||||
|
# label # this is the label that the subplot will take (since we create a layout before initialization)
|
||||||
end
|
end
|
||||||
EmptyLayout(parent = RootLayout()) = EmptyLayout(parent, defaultbox)
|
EmptyLayout(parent = RootLayout(); kw...) = EmptyLayout(parent, defaultbox, KW(kw))
|
||||||
|
|
||||||
# this is the parent of the top-level layout
|
# this is the parent of the top-level layout
|
||||||
immutable RootLayout <: AbstractLayout
|
immutable RootLayout <: AbstractLayout
|
||||||
@ -158,7 +155,7 @@ 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
|
plotarea::BoundingBox # the part where the data goes
|
||||||
subplotargs::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
|
||||||
plt # the enclosing Plot object (can't give it a type because of no forward declarations)
|
plt # the enclosing Plot object (can't give it a type because of no forward declarations)
|
||||||
@ -216,6 +213,9 @@ type Series
|
|||||||
d::KW
|
d::KW
|
||||||
end
|
end
|
||||||
|
|
||||||
|
attr(series::Series, k::Symbol) = series.d[k]
|
||||||
|
attr!(series::Series, v, k::Symbol) = (series.d[k] = v)
|
||||||
|
|
||||||
type Plot{T<:AbstractBackend} <: AbstractPlot{T}
|
type Plot{T<:AbstractBackend} <: AbstractPlot{T}
|
||||||
backend::T # the backend type
|
backend::T # the backend type
|
||||||
n::Int # number of series
|
n::Int # number of series
|
||||||
@ -232,6 +232,13 @@ function Plot()
|
|||||||
Subplot[], SubplotMap(), EmptyLayout())
|
Subplot[], SubplotMap(), EmptyLayout())
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO: make a decision... should plt[1] return the first subplot or the first series??
|
||||||
|
# Base.getindex(plt::Plot, i::Integer) = plt.subplots[i]
|
||||||
|
Base.getindex(plt::Plot, s::Symbol) = plt.spmap[s]
|
||||||
|
Base.getindex(plt::Plot, r::Integer, c::Integer) = plt.layout[r,c]
|
||||||
|
attr(plt::Plot, k::Symbol) = plt.plotargs[k]
|
||||||
|
attr!(plt::Plot, v, k::Symbol) = (plt.plotargs[k] = v)
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
# Subplot
|
# Subplot
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user