From 6076b9c129de33c3d3b6ba4539c4c512a2c32694 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 30 Jul 2021 14:48:12 -0500 Subject: [PATCH 1/3] Comment out precompile --- src/GridLayoutBase.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/GridLayoutBase.jl b/src/GridLayoutBase.jl index b51f25e..a376540 100644 --- a/src/GridLayoutBase.jl +++ b/src/GridLayoutBase.jl @@ -39,9 +39,9 @@ export protrusionsobservable, suggestedbboxobservable, reportedsizeobservable, a export ncols, nrows export contents, content -if Base.VERSION >= v"1.4.2" - include("precompile.jl") - _precompile_() -end +# if Base.VERSION >= v"1.4.2" +# include("precompile.jl") +# _precompile_() +# end end From 96f33090bf143cd68effef63f7723763a8a72878 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 30 Jul 2021 14:47:11 -0500 Subject: [PATCH 2/3] Improve inferrability and use enums rather than types for some settings --- Project.toml | 2 +- src/GridLayoutBase.jl | 8 ++- src/geometry_integration.jl | 15 ++-- src/gridlayout.jl | 125 ++++++++++++++++----------------- src/gridlayoutspec.jl | 4 +- src/layout_engine.jl | 133 +++++++++++++----------------------- src/layoutobservables.jl | 18 ++--- src/types.jl | 78 ++++++++++----------- test/debugrect.jl | 40 ++++++----- test/runtests.jl | 104 ++++++++++++++-------------- 10 files changed, 244 insertions(+), 283 deletions(-) diff --git a/Project.toml b/Project.toml index c7f7847..03f6875 100644 --- a/Project.toml +++ b/Project.toml @@ -12,7 +12,7 @@ Observables = "510215fc-4207-5dde-b226-833fc4488ee2" [compat] GeometryBasics = "0.4.1" Match = "^1" -Observables = "0.3, 0.4" +Observables = "0.4" julia = "1" [extras] diff --git a/src/GridLayoutBase.jl b/src/GridLayoutBase.jl index a376540..56ef88a 100644 --- a/src/GridLayoutBase.jl +++ b/src/GridLayoutBase.jl @@ -1,11 +1,15 @@ module GridLayoutBase +if isdefined(Base, :Experimental) && isdefined(Base.Experimental, Symbol("@compiler_options")) + @eval Base.Experimental.@compiler_options compile=min optimize=1 +end + using GeometryBasics using Observables using Match -const DEFAULT_COLGAP = Ref{Any}(20.0) -const DEFAULT_ROWGAP = Ref{Any}(20.0) +const DEFAULT_COLGAP = Ref{Float64}(20.0) +const DEFAULT_ROWGAP = Ref{Float64}(20.0) # These function refs can be mutated by other packages to override the default # way of retrieving default column and row gap sizes const DEFAULT_ROWGAP_GETTER = Ref{Function}(() -> DEFAULT_ROWGAP[]) diff --git a/src/geometry_integration.jl b/src/geometry_integration.jl index 22deb16..99ed623 100644 --- a/src/geometry_integration.jl +++ b/src/geometry_integration.jl @@ -7,12 +7,13 @@ width(rect::Rect{2}) = right(rect) - left(rect) height(rect::Rect{2}) = top(rect) - bottom(rect) -function BBox(left::Number, right::Number, bottom::Number, top::Number) +function BBox(left::Float32, right::Float32, bottom::Float32, top::Float32) mini = (left, bottom) maxi = (right, top) return Rect2f(mini, maxi .- mini) end - +BBox(left::Number, right::Number, bottom::Number, top::Number) = + BBox(Float32(left)::Float32, Float32(right)::Float32, Float32(bottom)::Float32, Float32(top)::Float32) function RowCols(ncols::Int, nrows::Int) return RowCols( @@ -23,17 +24,17 @@ function RowCols(ncols::Int, nrows::Int) ) end -Base.getindex(rowcols::RowCols, ::Left) = rowcols.lefts -Base.getindex(rowcols::RowCols, ::Right) = rowcols.rights -Base.getindex(rowcols::RowCols, ::Top) = rowcols.tops -Base.getindex(rowcols::RowCols, ::Bottom) = rowcols.bottoms +Base.getindex(rowcols::RowCols, side::Side) = side == Left ? rowcols.lefts : + side == Right ? rowcols.rights : + side == Top ? rowcols.tops : + side == Bottom ? rowcols.bottoms : throw_side(side) """ eachside(f) Calls f over all sides (Left, Right, Top, Bottom), and creates a BBox from the result of f(side) """ function eachside(f) -    return BBox(f(Left()), f(Right()), f(Bottom()), f(Top())) +    return BBox(f(Left), f(Right), f(Bottom), f(Top)) end """ diff --git a/src/gridlayout.jl b/src/gridlayout.jl index df651d2..30b4f6c 100644 --- a/src/gridlayout.jl +++ b/src/gridlayout.jl @@ -1,7 +1,9 @@ -GridLayout(; kwargs...) = GridLayout(1, 1; kwargs...) +GridLayout(; @nospecialize(kwargs...)) = GridLayout(1, 1; kwargs...) observablify(x::Observable) = x -observablify(x, type=Any) = Observable{type}(x) +observablify(x) = Observable(x) +struct Observablify{T} end +Observablify{T}(x) where T = convert(Observable{T}, x)::Observable{T} function GridLayout(nrows::Int, ncols::Int; parent = nothing, @@ -9,37 +11,38 @@ function GridLayout(nrows::Int, ncols::Int; colsizes = nothing, addedrowgaps = nothing, addedcolgaps = nothing, - alignmode = Inside(), + alignmode::AlignMode = Inside(), equalprotrusiongaps = (false, false), bbox = nothing, width::SizeAttribute = Auto(), height::SizeAttribute = Auto(), tellwidth::Bool = true, tellheight::Bool = true, - halign = :center, - valign = :center, - default_rowgap = DEFAULT_ROWGAP_GETTER[](), - default_colgap = DEFAULT_COLGAP_GETTER[](), + halign::AlignAttribute = :center, + valign::AlignAttribute = :center, + default_rowgap = DEFAULT_ROWGAP_GETTER[]()::Float64, + default_colgap = DEFAULT_COLGAP_GETTER[]()::Float64, kwargs...) + @nospecialize - default_rowgap::GapSize = default_rowgap isa Number ? Fixed(default_rowgap)::Fixed : default_rowgap - default_colgap::GapSize = default_colgap isa Number ? Fixed(default_colgap)::Fixed : default_colgap - rowsizes = convert_contentsizes(nrows, rowsizes) - colsizes = convert_contentsizes(ncols, colsizes) - addedrowgaps = convert_gapsizes(nrows - 1, addedrowgaps, default_rowgap) - addedcolgaps = convert_gapsizes(ncols - 1, addedcolgaps, default_colgap) + default_rowgap = (default_rowgap isa Number ? Fixed(default_rowgap) : default_rowgap)::GapSize + default_colgap = (default_colgap isa Number ? Fixed(default_colgap) : default_colgap)::GapSize + rowsizes = convert_contentsizes(nrows, rowsizes)::Vector{ContentSize} + colsizes = convert_contentsizes(ncols, colsizes)::Vector{ContentSize} + addedrowgaps = convert_gapsizes(nrows - 1, addedrowgaps, default_rowgap)::Vector{GapSize} + addedcolgaps = convert_gapsizes(ncols - 1, addedcolgaps, default_colgap)::Vector{GapSize} needs_update = Observable(true) - content = GridContent[] + content = GridContent{GridLayout}[] - alignmode = observablify(alignmode, AlignMode) - width = observablify(width) - height = observablify(height) - tellwidth = observablify(tellwidth) - tellheight = observablify(tellheight) - halign = observablify(halign) - valign = observablify(valign) + alignmode = Observablify{AlignMode}(alignmode) + width = Observablify{SizeAttribute}(width) + height = Observablify{SizeAttribute}(height) + tellwidth = Observable(tellwidth) + tellheight = Observable(tellheight) + halign = Observable{AlignAttribute}(halign) + valign = Observable{AlignAttribute}(valign) layoutobservables = layoutobservables = LayoutObservables{GridLayout}(width, height, tellwidth, tellheight, halign, valign; @@ -65,15 +68,15 @@ end function update!(gl::GridLayout) gl.block_updates && return - w = determinedirsize(gl, Col()) - h = determinedirsize(gl, Row()) + w = determinedirsize(gl, Col) + h = determinedirsize(gl, Row) new_autosize = (w, h) new_protrusions = RectSides{Float32}( - protrusion(gl, Left()), - protrusion(gl, Right()), - protrusion(gl, Bottom()), - protrusion(gl, Top()), + protrusion(gl, Left), + protrusion(gl, Right), + protrusion(gl, Bottom), + protrusion(gl, Top), ) if autosizeobservable(gl)[] == new_autosize && @@ -204,7 +207,7 @@ function remove_from_gridlayout!(gc::GridContent) end -function convert_contentsizes(n, sizes)::Vector{ContentSize} +function convert_contentsizes(n, @nospecialize(sizes))::Vector{ContentSize} if sizes === nothing ContentSize[Auto() for _ in 1:n] elseif sizes isa ContentSize @@ -450,7 +453,7 @@ end function Base.isempty(gl::GridLayout, dir::GridDir, i::Int) !any(gl.content) do c - span = dir isa Row ? c.span.rows : c.span.cols + span = dir == Row ? c.span.rows : c.span.cols i in span end end @@ -458,7 +461,7 @@ end function trim!(gl::GridLayout) irow = 1 while irow <= gl.nrows && gl.nrows > 1 - if isempty(gl, Row(), irow) + if isempty(gl, Row, irow) deleterow!(gl, irow) else irow += 1 @@ -467,7 +470,7 @@ function trim!(gl::GridLayout) icol = 1 while icol <= gl.ncols && gl.ncols > 1 - if isempty(gl, Col(), icol) + if isempty(gl, Col, icol) deletecol!(gl, icol) else icol += 1 @@ -681,8 +684,8 @@ function align_to_bbox!(gl::GridLayout, suggestedbbox::Rect2f) elseif alignmode isa Outside width(bbox) - sumcolgaps - leftprot - rightprot elseif alignmode isa Mixed - rightal = getside(alignmode, Right()) - leftal = getside(alignmode, Left()) + rightal = getside(alignmode, Right) + leftal = getside(alignmode, Left) width(bbox) - sumcolgaps - (isnothing(leftal) ? zero(leftprot) : isa(leftal, Protrusion) ? leftal.p : leftprot) - (isnothing(rightal) ? zero(rightprot) : isa(rightal, Protrusion) ? rightal.p : rightprot) @@ -695,8 +698,8 @@ function align_to_bbox!(gl::GridLayout, suggestedbbox::Rect2f) elseif alignmode isa Outside height(bbox) - sumrowgaps - topprot - bottomprot elseif alignmode isa Mixed - topal = getside(alignmode, Top()) - bottomal = getside(alignmode, Bottom()) + topal = getside(alignmode, Top) + bottomal = getside(alignmode, Bottom) height(bbox) - sumrowgaps - (isnothing(bottomal) ? zero(bottomprot) : isa(bottomal, Protrusion) ? bottomal.p : bottomprot) - (isnothing(topal) ? zero(topprot) : isa(topal, Protrusion) ? topal.p : topprot) @@ -759,7 +762,7 @@ function align_to_bbox!(gl::GridLayout, suggestedbbox::Rect2f) left(bbox) .+ zcumsum(colwidths[1:end-1]) .+ zcumsum(finalcolgaps) .+ leftprot elseif alignmode isa Mixed - leftal = getside(alignmode, Left()) + leftal = getside(alignmode, Left) left(bbox) .+ zcumsum(colwidths[1:end-1]) .+ zcumsum(finalcolgaps) .+ (isnothing(leftal) ? zero(leftprot) : isa(leftal, Protrusion) ? leftal.p : leftprot) else @@ -775,7 +778,7 @@ function align_to_bbox!(gl::GridLayout, suggestedbbox::Rect2f) top(bbox) .- zcumsum(rowheights[1:end-1]) .- zcumsum(finalrowgaps) .- topprot elseif alignmode isa Mixed - topal = getside(alignmode, Top()) + topal = getside(alignmode, Top) top(bbox) .- zcumsum(rowheights[1:end-1]) .- zcumsum(finalrowgaps) .- (isnothing(topal) ? zero(topprot) : isa(topal, Protrusion) ? topal.p : topprot) else @@ -809,8 +812,7 @@ function align_to_bbox!(gl::GridLayout, suggestedbbox::Rect2f) end -dirlength(gl::GridLayout, c::Col) = gl.ncols -dirlength(gl::GridLayout, r::Row) = gl.nrows +dirlength(gl::GridLayout, rc::GridDir) = rc == Col ? gl.ncols : gl.nrows function dirgaps(gl::GridLayout, dir::GridDir) starts = zeros(Float32, dirlength(gl, dir)) @@ -825,8 +827,7 @@ function dirgaps(gl::GridLayout, dir::GridDir) starts, stops end -dirsizes(gl::GridLayout, c::Col) = gl.colsizes -dirsizes(gl::GridLayout, r::Row) = gl.rowsizes +dirsizes(gl::GridLayout, rc::GridDir) = rc == Col ? gl.colsizes : gl.rowsizes """ Determine the size of a grid layout along one of its dimensions. @@ -853,7 +854,7 @@ function determinedirsize(gl::GridLayout, gdir::GridDir) dirgapsstart, dirgapsstop = dirgaps(gl, gdir) - forceequalprotrusiongaps = gl.equalprotrusiongaps[gdir isa Row ? 1 : 2] + forceequalprotrusiongaps = gl.equalprotrusiongaps[gdir == Row ? 1 : 2] dirgapsizes = if forceequalprotrusiongaps innergaps = dirgapsstart[2:end] .+ dirgapsstop[1:end-1] @@ -865,7 +866,7 @@ function determinedirsize(gl::GridLayout, gdir::GridDir) inner_gapsizes = dirlength(gl, gdir) > 1 ? sum(dirgapsizes) : 0 - addeddirgapsizes = gdir isa Row ? gl.addedrowgaps : gl.addedcolgaps + addeddirgapsizes = gdir == Row ? gl.addedrowgaps : gl.addedcolgaps addeddirgaps = dirlength(gl, gdir) == 1 ? 0 : sum(addeddirgapsizes) do c if c isa Fixed @@ -879,7 +880,7 @@ function determinedirsize(gl::GridLayout, gdir::GridDir) return if gl.alignmode[] isa Inside inner_size_combined elseif gl.alignmode[] isa Outside - paddings = if gdir isa Row + paddings = if gdir == Row gl.alignmode[].padding.top + gl.alignmode[].padding.bottom else gl.alignmode[].padding.left + gl.alignmode[].padding.right @@ -916,7 +917,7 @@ function determinedirsize(idir, gl, dir::GridDir) # content has to be placed with Inner side, otherwise it's protrusion # content - is_inner = c.side isa Inner + is_inner = c.side == Inner if singlespanned && is_inner s = determinedirsize(c.content, dir, c.side) @@ -979,14 +980,14 @@ function compute_col_row_sizes(spaceforcolumns, spaceforrows, gl) # then determinable auto sizes filterenum(Auto, gl.colsizes) do (i, auto) - size = determinedirsize(i, gl, Col()) + size = determinedirsize(i, gl, Col) if !isnothing(size) colwidths[i] = size determinedcols[i] = true end end filterenum(Auto, gl.rowsizes) do (i, auto) - size = determinedirsize(i, gl, Row()) + size = determinedirsize(i, gl, Row) if !isnothing(size) rowheights[i] = size determinedrows[i] = true @@ -1134,8 +1135,8 @@ function compute_col_row_sizes(spaceforcolumns, spaceforrows, gl) colwidths, rowheights end -function Base.setindex!(g::GridLayout, content, rows::Indexables, cols::Indexables, side::Side = Inner()) - add_content!(g, content, rows, cols, side) +function Base.setindex!(g::GridLayout, @nospecialize(content), rows::Indexables, cols::Indexables, side::Side = Inner) + add_content!(g, Base.inferencebarrier(content), rows, cols, side) content end @@ -1145,7 +1146,7 @@ function Base.setindex!(g::GridLayout, content_array::AbstractArray{T, 2}) where g[rowrange, colrange] = content_array end -function Base.setindex!(g::GridLayout, content_array::AbstractArray{T, 1}) where T +function Base.setindex!(g::GridLayout, content_array::AbstractVector) error(""" You can only assign a one-dimensional content AbstractArray if you also specify the direction in the layout. Valid options are :h for horizontal and :v for vertical. @@ -1154,7 +1155,7 @@ function Base.setindex!(g::GridLayout, content_array::AbstractArray{T, 1}) where """) end -function Base.setindex!(g::GridLayout, content_array::AbstractArray{T, 1}, h_or_v::Symbol) where T +function Base.setindex!(g::GridLayout, content_array::AbstractVector, h_or_v::Symbol) if h_or_v == :h g[1, 1:length(content_array)] = content_array elseif h_or_v == :v @@ -1205,7 +1206,7 @@ function Base.setindex!(g::GridLayout, content_array::AbstractArray, rows::Index content_array end -function GridContent(content::T, span::Span, side::Side) where T +function GridContent{G}(@nospecialize(content), span::Span, side::Side) where G needs_update = Observable(false) # connect the correct observables protrusions_handle = on(protrusionsobservable(content)) do p @@ -1214,25 +1215,25 @@ function GridContent(content::T, span::Span, side::Side) where T reportedsize_handle = on(reportedsizeobservable(content)) do c needs_update[] = true end - GridContent{GridLayout, T}(nothing, content, span, side, needs_update, + GridContent{G}(nothing, content, span, side, needs_update, protrusions_handle, reportedsize_handle) end -function add_content!(g::GridLayout, content, rows, cols, side::Side) +function add_content!(g::GridLayout, @nospecialize(content), rows::Indexables, cols::Indexables, side::Side) # update = false because update is called in add_to_gridlayout! anyway rows, cols = adjust_rows_cols!(g, rows, cols; update = false) - gc = if !isnothing(gridcontent(content)) + gridc = gridcontent(content) + gc = if !isnothing(gridc) # take the existing gridcontent, remove it from its gridlayout if it has one, # and modify it with the new span and side - gridc = gridcontent(content) remove_from_gridlayout!(gridc) gridc.span = Span(rows, cols) gridc.side = side gridc else # make a new one if none existed - GridContent(content, Span(rows, cols), side) + GridContent{GridLayout}(content, Span(rows, cols), side) end layoutobservables(content).gridcontent = gc @@ -1252,12 +1253,12 @@ function Base.lastindex(g::GridLayout, d) end end -function GridPosition(g::GridLayout, rows::Indexables, cols::Indexables, side = Inner()) +function GridPosition(g::GridLayout, rows::Indexables, cols::Indexables, side = Inner) span = Span(to_ranges(g, rows, cols)...) GridPosition(g, span, side) end -function Base.getindex(g::GridLayout, rows::Indexables, cols::Indexables, side = Inner()) +function Base.getindex(g::GridLayout, rows::Indexables, cols::Indexables, side = Inner) GridPosition(g, rows, cols, side) end @@ -1265,7 +1266,7 @@ function Base.setindex!(gp::GridPosition, element) gp.layout[gp.span.rows, gp.span.cols, gp.side] = element end -function Base.setindex!(gp::GridPosition, element, rows, cols, side = Inner()) +function Base.setindex!(gp::GridPosition, element, rows, cols, side = Inner) layout = get_layout_at!(gp, createmissing = true) layout[rows, cols, side] = element element @@ -1316,12 +1317,12 @@ function contents(g::GridLayout) end -function Base.getindex(gp::Union{GridPosition, GridSubposition}, rows, cols, side = Inner()) +function Base.getindex(gp::Union{GridPosition, GridSubposition}, rows, cols, side = Inner) GridSubposition(gp, rows, cols, side) end function Base.setindex!(parent::GridSubposition, obj, - rows, cols, side = GridLayoutBase.Inner()) + rows, cols, side = GridLayoutBase.Inner) layout = get_layout_at!(parent, createmissing = true) layout[rows, cols, side] = obj obj diff --git a/src/gridlayoutspec.jl b/src/gridlayoutspec.jl index dd17bec..1f3e696 100644 --- a/src/gridlayoutspec.jl +++ b/src/gridlayoutspec.jl @@ -12,8 +12,8 @@ function GridLayout(spec::GridLayoutSpec) end const PosTuple = Tuple{Indexables, Indexables, Side} -to_valid_pos(pos::Tuple{Indexables, Indexables}) = (pos[1], pos[2], Inner()) -to_valid_pos(pos::Tuple{Indexables, Indexables, Side}) = pos +to_valid_pos(pos::Tuple{Indexables, Indexables}) = (pos[1], pos[2], Inner) +to_valid_pos(pos::PosTuple) = pos function GridLayoutSpec(content::Vector{<:Pair}; kwargs...) spec_content = Pair{PosTuple, Any}[Pair{PosTuple, Any}(to_valid_pos(pos), c) for (pos, c) in content] diff --git a/src/layout_engine.jl b/src/layout_engine.jl index 6e04eb7..9f46b0c 100644 --- a/src/layout_engine.jl +++ b/src/layout_engine.jl @@ -14,65 +14,42 @@ end # These functions tell whether an object in a grid touches the left, top, etc. border # of the grid. This means that it is relevant for the grid's own protrusion on that side. -ismostin(gc::GridContent, grid, ::Left) = gc.span.cols.start == 1 -ismostin(gc::GridContent, grid, ::Right) = gc.span.cols.stop == grid.ncols -ismostin(gc::GridContent, grid, ::Bottom) = gc.span.rows.stop == grid.nrows -ismostin(gc::GridContent, grid, ::Top) = gc.span.rows.start == 1 +ismostin(gc::GridContent, grid, side::Side) = side == Left ? (gc.span.cols.start == 1) : + side == Right ? (gc.span.cols.stop == grid.ncols) : + side == Bottom ? (gc.span.rows.stop == grid.nrows) : + side == Top ? (gc.span.rows.start == 1) : throw_side(side) function protrusion(x::T, side::Side) where T protrusions = protrusionsobservable(x) - @match side begin - si::Left => protrusions[].left - si::Right => protrusions[].right - si::Bottom => protrusions[].bottom - si::Top => protrusions[].top - si => error("Can't get a protrusion value for side $(typeof(si)), only - Left, Right, Bottom, or Top.") - end + return side == Left ? protrusions[].left : + side == Right ? protrusions[].right : + side == Bottom ? protrusions[].bottom : + side == Top ? protrusions[].top : + error("Can't get a protrusion value for side $side, only Left, Right, Bottom, or Top.") end function protrusion(gc::GridContent, side::Side) - prot = @match gc.side begin - gcside::Inner => protrusion(gc.content, side) - # gcside::Outer => BBox(l - pl, r + pr, b - pb, t + pt) - gcside::Union{Left, Right} => @match side begin - si::typeof(gcside) => determinedirsize(gc.content, Col(), gc.side) - si => 0.0 - end - gcside::Union{Top, Bottom} => @match side begin - si::typeof(gcside) => determinedirsize(gc.content, Row(), gc.side) - si => 0.0 - end - gcside::TopLeft => @match side begin - si::Top => determinedirsize(gc.content, Row(), gc.side) - si::Left => determinedirsize(gc.content, Col(), gc.side) - si => 0.0 - end - gcside::TopRight => @match side begin - si::Top => determinedirsize(gc.content, Row(), gc.side) - si::Right => determinedirsize(gc.content, Col(), gc.side) - si => 0.0 - end - gcside::BottomLeft => @match side begin - si::Bottom => determinedirsize(gc.content, Row(), gc.side) - si::Left => determinedirsize(gc.content, Col(), gc.side) - si => 0.0 - end - gcside::BottomRight => @match side begin - si::Bottom => determinedirsize(gc.content, Row(), gc.side) - si::Right => determinedirsize(gc.content, Col(), gc.side) - si => 0.0 - end - gcside => error("Invalid side $gcside") - end + gcside = gc.side + prot = gcside == Inner ? protrusion(gc.content, side) : + # gcside == Outer ? BBox(l - pl, r + pr, b - pb, t + pt) : + gcside ∈ (Left, Right) ? (side == gcside ? determinedirsize(gc.content, Col, gcside) : 0.0) : + gcside ∈ (Top, Bottom) ? (side == gcside ? determinedirsize(gc.content, Row, gcside) : 0.0) : + gcside == TopLeft ? (side ∈ (Top, Left) ? determinedirsize(gc.content, GridDir(side), gcside) : 0.0) : + gcside == TopRight ? (side ∈ (Top, Right) ? determinedirsize(gc.content, GridDir(side), gcside) : 0.0) : + gcside == BottomLeft ? (side ∈ (Bottom, Left) ? determinedirsize(gc.content, GridDir(side), gcside) : 0.0) : + gcside == BottomRight ? (side ∈ (Bottom, Right) ? determinedirsize(gc.content, GridDir(side), gcside) : 0.0) : + throw_side(gcside) ifnothing(prot, 0.0) end -getside(m::Mixed, ::Left) = m.sides.left -getside(m::Mixed, ::Right) = m.sides.right -getside(m::Mixed, ::Top) = m.sides.top -getside(m::Mixed, ::Bottom) = m.sides.bottom +function getside(m::Mixed, side::Side) + msides = m.sides + return side == Left ? msides.left : + side == Right ? msides.right : + side == Top ? msides.top : + side == Bottom ? msides.bottom : throw_side(side) +end function inside_protrusion(gl::GridLayout, side::Side) prot = 0.0 @@ -118,29 +95,23 @@ function bbox_for_solving_from_side(maxgrid::RowCols, bbox_cell::Rect2f, idx_rec b = bottom(bbox_cell) t = top(bbox_cell) - @match side begin - s::Inner => bbox_cell - s::Outer => BBox(l - pl, r + pr, b - pb, t + pt) - s::Left => BBox(l - pl, l, b, t) - s::Top => BBox(l, r, t, t + pt) - s::Right => BBox(r, r + pr, b, t) - s::Bottom => BBox(l, r, b - pb, b) - s::TopLeft => BBox(l - pl, l, t, t + pt) - s::TopRight => BBox(r, r + pr, t, t + pt) - s::BottomRight => BBox(r, r + pr, b - pb, b) - s::BottomLeft => BBox(l - pl, l, b - pb, b) - s => error("Invalid side $s") - end + return side == Inner ? bbox_cell : + side == Outer ? BBox(l - pl, r + pr, b - pb, t + pt) : + side == Left ? BBox(l - pl, l, b, t) : + side == Top ? BBox(l, r, t, t + pt) : + side == Right ? BBox(r, r + pr, b, t) : + side == Bottom ? BBox(l, r, b - pb, b) : + side == TopLeft ? BBox(l - pl, l, t, t + pt) : + side == TopRight ? BBox(r, r + pr, t, t + pt) : + side == BottomRight ? BBox(r, r + pr, b - pb, b) : + side == BottomLeft ? BBox(l - pl, l, b - pb, b) : throw_side(side) end -startside(c::Col) = Left() -stopside(c::Col) = Right() -startside(r::Row) = Top() -stopside(r::Row) = Bottom() +startside(rc::GridDir) = rc == Row ? Top : Left +stopside(rc::GridDir) = rc == Row ? Bottom : Right -getspan(gc::GridContent, dir::Col) = gc.span.cols -getspan(gc::GridContent, dir::Row) = gc.span.rows +getspan(gc::GridContent, dir::GridDir) = dir == Col ? gc.span.cols : gc.span.rows @@ -151,23 +122,15 @@ means that the protrusion layout reports its width but not its protrusions. `Lef means that the layout reports only its full width but not its height, because an element placed in the left protrusion loses its ability to influence height. """ -function determinedirsize(content, gdir::GridDir, side::Side) - reportedsize = reportedsizeobservable(content) - if gdir isa Row - @match side begin - # TODO: is reportedsize the correct thing to return? or plus protrusions depending on the side - si::Union{Inner, Top, Bottom, TopLeft, TopRight, BottomLeft, BottomRight} => - ifnothing(reportedsize[][2], nothing) - si::Union{Left, Right} => nothing - si => error("$side not implemented") - end +determinedirsize(content, gdir::GridDir, side::Side) = _determinedirsize(reportedsizeobservable(content), gdir, side) +@noinline function _determinedirsize(reportedsize, gdir::GridDir, side::Side) + if gdir == Row + # TODO: is reportedsize the correct thing to return? or plus protrusions depending on the side + side ∈ (Inner, Top, Bottom, TopLeft, TopRight, BottomLeft, BottomRight) ? reportedsize[][2] : + side ∈ (Left, Right) ? nothing : throw_side(side) else - @match side begin - si::Union{Inner, Left, Right, TopLeft, TopRight, BottomLeft, BottomRight} => - ifnothing(reportedsize[][1], nothing) - si::Union{Top, Bottom} => nothing - si => error("$side not implemented") - end + side ∈ (Inner, Left, Right, TopLeft, TopRight, BottomLeft, BottomRight) ? reportedsize[][1] : + side ∈ (Top, Bottom) ? nothing : throw_side(side) end end @@ -185,7 +148,7 @@ function to_ranges(g::GridLayout, rows::Indexables, cols::Indexables) rows, cols end -function adjust_rows_cols!(g::GridLayout, rows, cols; update = true) +function adjust_rows_cols!(g::GridLayout, rows::Indexables, cols::Indexables; update = true) rows, cols = to_ranges(g, rows, cols) if rows.start < 1 diff --git a/src/layoutobservables.jl b/src/layoutobservables.jl index a4f08e4..024bc2e 100644 --- a/src/layoutobservables.jl +++ b/src/layoutobservables.jl @@ -18,7 +18,7 @@ function align_shift_tuple(halign::Union{Number, Symbol}, valign::Union{Number, return (halign2shift(halign), valign2shift(valign)) end -function LayoutObservables{T}(width::Observable, height::Observable, +function LayoutObservables{G}(width::Observable, height::Observable, tellwidth::Observable, tellheight::Observable, halign::Observable, valign::Observable, alignmode::Observable = Observable{AlignMode}(Inside()); suggestedbbox = nothing, @@ -26,13 +26,13 @@ function LayoutObservables{T}(width::Observable, height::Observable, reportedsize = nothing, autosize = nothing, computedbbox = nothing, - gridcontent = nothing) where T - + gridcontent = nothing) where G + @nospecialize sizeobservable = sizeobservable!(width, height) alignment = map(align_shift_tuple, halign, valign) - suggestedbbox_observable = create_suggested_bboxobservable(suggestedbbox) - protrusions = create_protrusions(protrusions) + suggestedbbox_observable = create_suggested_bboxobservable(suggestedbbox)::Observable{Rect2f} + protrusions = create_protrusions(protrusions)::Observable{RectSides{Float32}} tellsizeobservable = map(tuple, tellwidth, tellheight) @@ -46,7 +46,7 @@ function LayoutObservables{T}(width::Observable, height::Observable, finalbbox = alignedbboxobservable!(suggestedbbox_observable, reportedsize, alignment, sizeobservable, autosizeobservable, alignmode, protrusions) - LayoutObservables{T, GridLayout}(suggestedbbox_observable, protrusions_after_alignmode, reportedsize, autosizeobservable, finalbbox, nothing) + LayoutObservables{G}(suggestedbbox_observable, protrusions_after_alignmode, reportedsize, autosizeobservable, finalbbox, nothing) end maprectsides(f) = RectSides(map(f, (:left, :right, :bottom, :top))...) @@ -90,7 +90,7 @@ create_protrusions(p::RectSides{Float32}) = Observable(p) function sizeobservable!(@nospecialize(widthattr::Observable), @nospecialize(heightattr::Observable)) - sizeattrs = Observable{Tuple{Any, Any}}((widthattr[], heightattr[])) + sizeattrs = Observable{Tuple{SizeAttribute, SizeAttribute}}((widthattr[], heightattr[])) onany(widthattr, heightattr) do w, h sizeattrs[] = (w, h) end @@ -103,8 +103,8 @@ function reportedsizeobservable!(sizeattrs, autosizeobservable::Observable{NTupl # set up rsizeobservable with correct type manually rsizeobservable = Observable{NTuple{2, Optional{Float32}}}((nothing, nothing)) - onany(sizeattrs, autosizeobservable, alignmode, protrusions, tellsizeobservable) do sizeattrs::Tuple{SizeAttribute,SizeAttribute}, - autosize, alignmode::AlignMode, protrusions, tellsizeobservable + onany(sizeattrs, autosizeobservable, alignmode, protrusions, tellsizeobservable) do sizeattrs, + autosize, alignmode, protrusions, tellsizeobservable rsizeobservable[] = _reportedsizeobservable(sizeattrs, autosize, alignmode, protrusions, tellsizeobservable) end diff --git a/src/types.jl b/src/types.jl index 20ed288..b7f5ad3 100644 --- a/src/types.jl +++ b/src/types.jl @@ -7,32 +7,21 @@ struct RectSides{T} top::T end -abstract type Side end - -struct Left <: Side end -struct Right <: Side end -struct Top <: Side end -struct Bottom <: Side end -# for protrusion content: -struct TopLeft <: Side end -struct TopRight <: Side end -struct BottomLeft <: Side end -struct BottomRight <: Side end - -struct Inner <: Side end -struct Outer <: Side end - -abstract type GridDir end -struct Col <: GridDir end -struct Row <: GridDir end - -struct RowCols{T <: Union{Number, Vector{Float64}}} +@enum Side Left Right Top Bottom #= protrusion content: =# TopLeft TopRight BottomLeft BottomRight Inner Outer +throw_side(side) = throw(ArgumentError("side $side not supported")) + + +@enum GridDir Col Row +GridDir(side::Side) = side ∈ (Top, Bottom) ? Row : + side ∈ (Left, Right) ? Col : throw_side(side) + +struct RowCols{T <: Union{Int, Vector{Float64}}} lefts::T rights::T tops::T bottoms::T end - +RowCols(left::Real, right::Real, top::Real, bottom::Real) = RowCols{Int}(left, right, top, bottom) """ struct Span @@ -41,18 +30,18 @@ Used to specify space that is occupied in a grid. Like 1:1|1:1 for the first squ or 2:3|1:4 for a rect over the 2nd and 3rd row and the first four columns. """ struct Span - rows::UnitRange{Int64} - cols::UnitRange{Int64} + rows::UnitRange{Int} + cols::UnitRange{Int} end """ - mutable struct GridContent{G, T} + mutable struct GridContent{G} Wraps content elements of a `GridLayout`. It keeps track of the `parent`, the `content` and its position in the grid via `span` and `side`. """ -mutable struct GridContent{G, T} # G should be GridLayout but can't be used before definition +mutable struct GridContent{G} # G should be GridLayout but can't be used before definition parent::Optional{G} - content::T + content # deliberately untyped (diverse) span::Span side::Side needs_update::Observable{Bool} @@ -133,8 +122,17 @@ struct Aspect <: ContentSize ratio::Float64 end +const Indexables = Union{UnitRange{Int}, Int, Colon} +const SizeAttribute = Union{Nothing, Float32, Fixed, Relative, Auto} +const AutoSize = Union{Nothing, Float32} +const AlignAttribute = Union{Float32, Symbol} + +Base.convert(::Type{SizeAttribute}, val::Real) = convert(Float32, val) +Base.convert(::Type{AlignAttribute}, val::Real) = convert(Float32, val) +Base.convert(::Type{AlignAttribute}, val::AbstractString) = Symbol(val) + """ - mutable struct LayoutObservables{T, G} + mutable struct LayoutObservables{G} `T` is the same type parameter of contained `GridContent`, `G` is `GridLayout` which is defined only after `LayoutObservables`. @@ -145,21 +143,21 @@ A collection of `Observable`s and an optional `GridContent` that are needed to i - `reportedsize::Observable{NTuple{2, Optional{Float32}}}`: The width and height that the element computes for itself if possible (else `nothing`). - `autosize::Observable{NTuple{2, Optional{Float32}}}`: The width and height that the element reports to its parent `GridLayout`. If the element doesn't want to cause the parent to adjust to its size, autosize can hide the reportedsize from it by being set to `nothing`. - `computedbbox::Observable{Rect2f}`: The bounding box that the element computes for itself after it has received a suggestedbbox. -- `gridcontent::Optional{GridContent{G, T}}`: A reference of a `GridContent` if the element is currently placed in a `GridLayout`. This can be used to retrieve the parent layout, remove the element from it or change its position, and assign it to a different layout. +- `gridcontent::Optional{GridContent{G}}`: A reference of a `GridContent` if the element is currently placed in a `GridLayout`. This can be used to retrieve the parent layout, remove the element from it or change its position, and assign it to a different layout. """ -mutable struct LayoutObservables{T, G} # G again GridLayout +mutable struct LayoutObservables{G} # G again GridLayout suggestedbbox::Observable{Rect2f} protrusions::Observable{RectSides{Float32}} reportedsize::Observable{NTuple{2, Optional{Float32}}} autosize::Observable{NTuple{2, Optional{Float32}}} computedbbox::Observable{Rect2f} - gridcontent::Optional{GridContent{G, T}} # the connecting link to the gridlayout + gridcontent::Optional{GridContent{G}} # the connecting link to the gridlayout end mutable struct GridLayout parent # this parent is supposed to be any kind of object where it's beneficial # to access it through the assigned GridLayout, like a Figure in Makie - content::Vector{GridContent} + content::Vector{GridContent{GridLayout}} nrows::Int ncols::Int rowsizes::Vector{ContentSize} @@ -170,13 +168,13 @@ mutable struct GridLayout equalprotrusiongaps::Tuple{Bool, Bool} needs_update::Observable{Bool} block_updates::Bool - layoutobservables::LayoutObservables - width::Observable - height::Observable - tellwidth::Observable - tellheight::Observable - halign::Observable - valign::Observable + layoutobservables::LayoutObservables{GridLayout} + width::Observable{SizeAttribute} + height::Observable{SizeAttribute} + tellwidth::Observable{Bool} + tellheight::Observable{Bool} + halign::Observable{AlignAttribute} + valign::Observable{AlignAttribute} default_rowgap::GapSize default_colgap::GapSize _update_func_handle::Optional{Function} # stores a reference to the result of on(obs) @@ -198,10 +196,6 @@ mutable struct GridLayout end end -const Indexables = Union{UnitRange, Int, Colon} -const SizeAttribute = Union{Nothing, Real, Fixed, Relative, Auto} -const AutoSize = Union{Nothing, Float32} - struct GridPosition layout::GridLayout span::Span diff --git a/test/debugrect.jl b/test/debugrect.jl index ed3866c..04f47c2 100644 --- a/test/debugrect.jl +++ b/test/debugrect.jl @@ -1,21 +1,19 @@ mutable struct DebugRect - layoutobservables::GridLayoutBase.LayoutObservables - width::Observable - height::Observable - tellwidth::Observable - tellheight::Observable - halign::Observable - valign::Observable - leftprot::Observable - rightprot::Observable - bottomprot::Observable - topprot::Observable - alignmode::Observable + layoutobservables::GridLayoutBase.LayoutObservables{GridLayout} + width::Observable{GridLayoutBase.SizeAttribute} + height::Observable{GridLayoutBase.SizeAttribute} + tellwidth::Observable{Bool} + tellheight::Observable{Bool} + halign::Observable{GridLayoutBase.AlignAttribute} + valign::Observable{GridLayoutBase.AlignAttribute} + leftprot::Observable{Float32} + rightprot::Observable{Float32} + bottomprot::Observable{Float32} + topprot::Observable{Float32} + alignmode::Observable{GridLayoutBase.AlignMode} end - -observablify(x::Observable) = x -observablify(x, type=Any) = Observable{type}(x) +using GridLayoutBase: observablify, Observablify function DebugRect(; bbox = nothing, width=nothing, height=nothing, tellwidth = true, tellheight = true, halign=:center, @@ -28,17 +26,17 @@ function DebugRect(; bbox = nothing, width=nothing, height=nothing, tellheight = observablify(tellheight) halign = observablify(halign) valign = observablify(valign) - topprot = observablify(topprot, Float32) - leftprot = observablify(leftprot, Float32) - rightprot = observablify(rightprot, Float32) - bottomprot = observablify(bottomprot, Float32) - alignmode = observablify(alignmode) + topprot = Observablify{Float32}(topprot) + leftprot = Observablify{Float32}(leftprot) + rightprot = Observablify{Float32}(rightprot) + bottomprot = Observablify{Float32}(bottomprot) + alignmode = Observablify{GridLayoutBase.AlignMode}(alignmode) protrusions::Observable{GridLayoutBase.RectSides{Float32}} = map(leftprot, rightprot, bottomprot, topprot) do l, r, b, t GridLayoutBase.RectSides{Float32}(l, r, b, t) end - layoutobservables = GridLayoutBase.LayoutObservables{DebugRect}(width, + layoutobservables = GridLayoutBase.LayoutObservables{GridLayout}(width, height, tellwidth, tellheight, halign, valign, alignmode; suggestedbbox = bbox, protrusions = protrusions) diff --git a/test/runtests.jl b/test/runtests.jl index 5360fa7..891f822 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -68,27 +68,27 @@ end layout = GridLayout(bbox = bbox, alignmode = Mixed(left = 0, top = 100)) dr = layout[1, 1] = DebugRect() - @test GridLayoutBase.protrusion(layout, Left()) == 0 - @test GridLayoutBase.protrusion(layout, Right()) == 0 - @test GridLayoutBase.protrusion(layout, Bottom()) == 0 - @test GridLayoutBase.protrusion(layout, Top()) == 0 + @test GridLayoutBase.protrusion(layout, Left) == 0 + @test GridLayoutBase.protrusion(layout, Right) == 0 + @test GridLayoutBase.protrusion(layout, Bottom) == 0 + @test GridLayoutBase.protrusion(layout, Top) == 0 @test computedbboxobservable(dr)[] == BBox(0, 1000, 0, 900) dr.topprot[] = 100 - @test GridLayoutBase.protrusion(layout, Top()) == 0 + @test GridLayoutBase.protrusion(layout, Top) == 0 @test computedbboxobservable(dr)[] == BBox(0, 1000, 0, 800) dr.bottomprot[] = 100 - @test GridLayoutBase.protrusion(layout, Bottom()) == 100 + @test GridLayoutBase.protrusion(layout, Bottom) == 100 @test computedbboxobservable(dr)[] == BBox(0, 1000, 0, 800) dr.leftprot[] = 100 - @test GridLayoutBase.protrusion(layout, Left()) == 0 + @test GridLayoutBase.protrusion(layout, Left) == 0 @test computedbboxobservable(dr)[] == BBox(100, 1000, 0, 800) dr.rightprot[] = 100 - @test GridLayoutBase.protrusion(layout, Right()) == 100 + @test GridLayoutBase.protrusion(layout, Right) == 100 @test computedbboxobservable(dr)[] == BBox(100, 1000, 0, 800) layout.alignmode[] = Mixed( @@ -99,10 +99,10 @@ end ) # set layout to forced protrusion alignment - @test GridLayoutBase.protrusion(layout, Left()) == 50 - @test GridLayoutBase.protrusion(layout, Right()) == 60 - @test GridLayoutBase.protrusion(layout, Bottom()) == 70 - @test GridLayoutBase.protrusion(layout, Top()) == 80 + @test GridLayoutBase.protrusion(layout, Left) == 50 + @test GridLayoutBase.protrusion(layout, Right) == 60 + @test GridLayoutBase.protrusion(layout, Bottom) == 70 + @test GridLayoutBase.protrusion(layout, Top) == 80 # bb of dr only depends on its protrusions now @test computedbboxobservable(dr)[] == BBox(100, 1000, 0, 800) @@ -134,35 +134,35 @@ end layout = GridLayout(bbox = bbox, alignmode = Outside(0)) subgl = layout[1, 1] = GridLayout() - subgl[1, 1, Left()] = DebugRect(width = Fixed(100)) - @test GridLayoutBase.protrusion(subgl, Left()) == 100 + subgl[1, 1, Left] = DebugRect(width = Fixed(100)) + @test GridLayoutBase.protrusion(subgl, Left) == 100 - subgl[1, 1, Top()] = DebugRect(height = 50) - @test GridLayoutBase.protrusion(subgl, Top()) == 50 + subgl[1, 1, Top] = DebugRect(height = 50) + @test GridLayoutBase.protrusion(subgl, Top) == 50 - subgl[1, 1, Right()] = DebugRect(width = 120) - @test GridLayoutBase.protrusion(subgl, Right()) == 120 + subgl[1, 1, Right] = DebugRect(width = 120) + @test GridLayoutBase.protrusion(subgl, Right) == 120 - subgl[1, 1, Bottom()] = DebugRect(height = 40) - @test GridLayoutBase.protrusion(subgl, Bottom()) == 40 + subgl[1, 1, Bottom] = DebugRect(height = 40) + @test GridLayoutBase.protrusion(subgl, Bottom) == 40 - subgl[1, 1, TopLeft()] = DebugRect(width = 200, height = 200) - @test GridLayoutBase.protrusion(subgl, Left()) == 200 - @test GridLayoutBase.protrusion(subgl, Top()) == 200 + subgl[1, 1, TopLeft] = DebugRect(width = 200, height = 200) + @test GridLayoutBase.protrusion(subgl, Left) == 200 + @test GridLayoutBase.protrusion(subgl, Top) == 200 - subgl[1, 1, TopRight()] = DebugRect(width = 210, height = 210) - @test GridLayoutBase.protrusion(subgl, Right()) == 210 - @test GridLayoutBase.protrusion(subgl, Top()) == 210 + subgl[1, 1, TopRight] = DebugRect(width = 210, height = 210) + @test GridLayoutBase.protrusion(subgl, Right) == 210 + @test GridLayoutBase.protrusion(subgl, Top) == 210 - subgl[1, 1, BottomRight()] = DebugRect(width = 220, height = 220) - @test GridLayoutBase.protrusion(subgl, Right()) == 220 - @test GridLayoutBase.protrusion(subgl, Bottom()) == 220 + subgl[1, 1, BottomRight] = DebugRect(width = 220, height = 220) + @test GridLayoutBase.protrusion(subgl, Right) == 220 + @test GridLayoutBase.protrusion(subgl, Bottom) == 220 - subgl[1, 1, BottomLeft()] = DebugRect(width = 230, height = 230) - @test GridLayoutBase.protrusion(subgl, Left()) == 230 - @test GridLayoutBase.protrusion(subgl, Bottom()) == 230 + subgl[1, 1, BottomLeft] = DebugRect(width = 230, height = 230) + @test GridLayoutBase.protrusion(subgl, Left) == 230 + @test GridLayoutBase.protrusion(subgl, Bottom) == 230 - # dr = subgl[1, 1, GridLayoutBase.Outer()] = DebugRect() + # dr = subgl[1, 1, GridLayoutBase.Outer] = DebugRect() # @test computedbboxobservable(dr)[].widths == (1000, 1000) end @@ -473,7 +473,7 @@ end layout = GridLayout(bbox = bbox, alignmode = Outside(0)) subgl = layout[1, 1] = GridLayout(3, 3, equalprotrusiongaps = (true, true), addedcolgaps = Fixed(0), addedrowgaps = Fixed(0)) - subgl[1, 1, BottomRight()] = DebugRect(width = 100, height = 100) + subgl[1, 1, BottomRight] = DebugRect(width = 100, height = 100) dr1 = subgl[1, 1] = DebugRect() dr2 = subgl[2, 2] = DebugRect() @@ -519,12 +519,12 @@ end co = contents(layout[:, :]) @test co == [dr1, dr2, dr3, dr4] - dr5 = layout[2, 2, Right()] = DebugRect() + dr5 = layout[2, 2, Right] = DebugRect() - co = contents(layout[:, :]) # implicit Inner() side + co = contents(layout[:, :]) # implicit Inner side @test co == [dr1, dr2, dr3, dr4] - @test contents(layout[2, 2, Right()]) == [dr5] + @test contents(layout[2, 2, Right]) == [dr5] dr6 = layout[1:2, 2] = DebugRect() @test contents(layout[1:2, 2]) == [dr2, dr4, dr6] @@ -551,26 +551,26 @@ end gl = GridLayout(;alignmode = Outside(0)) gl[1, 1] = DebugRect(width = 800, height = 600) - @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row()) == 600 - @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col()) == 800 + @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row) == 600 + @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col) == 800 - gl[1, 1, Left()] = DebugRect(width = 200) - @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col()) == 800 + 200 - gl[1, 1, Right()] = DebugRect(width = 200) - @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col()) == 800 + 200 + 200 + gl[1, 1, Left] = DebugRect(width = 200) + @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col) == 800 + 200 + gl[1, 1, Right] = DebugRect(width = 200) + @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col) == 800 + 200 + 200 - gl[1, 1, Top()] = DebugRect(height = 100) - @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row()) == 600 + 100 - gl[1, 1, Bottom()] = DebugRect(height = 100) - @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row()) == 600 + 100 + 100 + gl[1, 1, Top] = DebugRect(height = 100) + @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row) == 600 + 100 + gl[1, 1, Bottom] = DebugRect(height = 100) + @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row) == 600 + 100 + 100 gl.alignmode[] = Outside(50) - @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col()) == 800 + 200 + 200 + 2 * 50 - @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row()) == 600 + 100 + 100 + 2 * 50 + @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col) == 800 + 200 + 200 + 2 * 50 + @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row) == 600 + 100 + 100 + 2 * 50 gl.alignmode[] = Inside() - @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col()) == 800 - @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row()) == 600 + @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Col) == 800 + @test GridLayoutBase.determinedirsize(gl, GridLayoutBase.Row) == 600 end @testset "alignment" begin @@ -625,7 +625,7 @@ end spec = GridLayoutSpec([ (1, 1) => dr, - (1:2, 4:5, Left()) => dr2, + (1:2, 4:5, Left) => dr2, (:, 0) => GridLayoutSpec([ (1:3, 2:4) => dr3 ]) From 7d5144483ff5dca935dbbe800886a1e7b12f3c30 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sat, 31 Jul 2021 12:26:45 -0500 Subject: [PATCH 3/3] Change how precompile works --- src/GridLayoutBase.jl | 7 ++-- src/precompile.jl | 85 +++++++------------------------------------ 2 files changed, 16 insertions(+), 76 deletions(-) diff --git a/src/GridLayoutBase.jl b/src/GridLayoutBase.jl index 56ef88a..e9c345f 100644 --- a/src/GridLayoutBase.jl +++ b/src/GridLayoutBase.jl @@ -43,9 +43,8 @@ export protrusionsobservable, suggestedbboxobservable, reportedsizeobservable, a export ncols, nrows export contents, content -# if Base.VERSION >= v"1.4.2" -# include("precompile.jl") -# _precompile_() -# end +if Base.VERSION >= v"1.4.2" && ccall(:jl_generating_output, Cint, ()) == 1 + include("precompile.jl") +end end diff --git a/src/precompile.jl b/src/precompile.jl index c783baa..1a1ff31 100644 --- a/src/precompile.jl +++ b/src/precompile.jl @@ -1,73 +1,14 @@ -using InteractiveUtils - -const Emptykwargs = Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}} - -macro warnpcfail(ex::Expr) - modl = __module__ - file = __source__.file === nothing ? "?" : String(__source__.file) - line = __source__.line - quote - $(esc(ex)) || @warn """precompile directive - $($(Expr(:quote, ex))) - failed. Please report an issue in $($modl) (after checking for duplicates) or remove this directive.""" _file=$file _line=$line - end -end - -function _precompile_() - ccall(:jl_generating_output, Cint, ()) == 1 || return nothing - @warnpcfail precompile(BBox, (Float32, Float32, Float64, Float64)) - - @warnpcfail precompile(GridLayout, (Int, Int)) - @warnpcfail precompile(GridLayout, (GridLayoutSpec,)) - @warnpcfail precompile(Core.kwfunc(GridLayout), (NamedTuple{(:bbox,), Tuple{Observable{Rect2i}}}, Type{GridLayout})) - @warnpcfail precompile(Core.kwfunc(GridLayout), (NamedTuple{(:bbox,), Tuple{Rect2f}}, Type{GridLayout})) - # Also precompile `GridLayout(bbox = bbox, alignmode = al)` and the keyword body method - fbody = isdefined(Base, :bodyfunction) ? Base.bodyfunction(which(GridLayout, (Int, Int))) : nothing - for Al in (Inside, Outside, Mixed) - @warnpcfail precompile(Core.kwfunc(GridLayout), (NamedTuple{(:bbox, :alignmode), Tuple{Rect2f, Al}}, Type{GridLayout})) - @warnpcfail precompile(Core.kwfunc(GridLayout), (NamedTuple{(:bbox, :alignmode), Tuple{Observable{Rect2f}, Al}}, Type{GridLayout})) - @warnpcfail precompile(Core.kwfunc(GridLayout), (NamedTuple{(:bbox, :alignmode), Tuple{NTuple{4,Int}, Al}}, Type{GridLayout})) - if fbody !== nothing - @warnpcfail precompile(fbody, (Nothing, Nothing, Nothing, Nothing, Nothing, Al, Tuple{Bool, Bool}, Rect2f, Auto, Auto, Bool, Bool, Symbol, Symbol, Float64, Float64, Emptykwargs, Type{GridLayout}, Int, Int)) - end - end - @warnpcfail precompile(Core.kwfunc(GridLayout), (NamedTuple{(:colsizes, :rowsizes), Tuple{Fixed, Relative}}, Type{GridLayout}, Int, Int)) - @warnpcfail precompile(Core.kwfunc(GridLayout), (NamedTuple{(:addedcolgaps,), Tuple{Vector{Fixed}}}, Type{GridLayout}, Int, Int)) - - @warnpcfail precompile(Core.kwfunc(Mixed), (NamedTuple{(:left, :top), Tuple{Int, Int}}, Type{Mixed})) - for T in (Int, Float32) - @warnpcfail precompile(Outside, (T,)) - @warnpcfail precompile(Outside, (T,T,T,T)) - end - @warnpcfail precompile(align_to_bbox!, (GridLayout, Rect2f)) - @warnpcfail precompile(update!, (GridLayout,)) - for I in subtypes(Indexables), J in subtypes(Indexables) - @warnpcfail precompile(setindex!, (GridLayout, UnitRange{Int}, I, J)) - @warnpcfail precompile(setindex!, (GridLayout, Any, I, J)) - end - @warnpcfail precompile(insertrows!, (GridLayout, Int, Int)) - @warnpcfail precompile(insertcols!, (GridLayout, Int, Int)) - @warnpcfail precompile(gridnest!, (GridLayout, UnitRange{Int}, UnitRange{Int})) - @warnpcfail precompile(add_to_gridlayout!, (GridLayout, GridContent{GridLayout, GridLayout})) - @warnpcfail precompile(connect_layoutobservables!, (GridContent{GridLayout, GridLayout},)) - @warnpcfail precompile(trim!, (GridLayout,)) - @warnpcfail precompile(sizeobservable!, (Observable{Any}, Observable{Any})) - @warnpcfail precompile(_reportedsizeobservable, (Tuple{SizeAttribute,SizeAttribute}, Tuple{AutoSize,AutoSize}, AlignMode, RectSides{Float32}, Tuple{Bool,Bool})) - for T in subtypes(Side) - @warnpcfail precompile(bbox_for_solving_from_side, (RowCols{Vector{Float64}}, Rect2f, RowCols{Int}, T)) - end - for S in (Left, Right, Top, Bottom) - @warnpcfail precompile(protrusion, (GridContent{GridLayout,GridLayout}, S)) - end - @warnpcfail precompile(suggestedbboxobservable, (GridLayout,)) - for VC in (Vector{Auto}, Vector{GapSize}, Vector{Fixed}, Vector{Relative}, Vector{ContentSize}) - @warnpcfail precompile(convert_contentsizes, (Int, VC)) - @warnpcfail precompile(==, (VC, VC)) - end - @warnpcfail precompile(contents, (GridLayout,)) - @warnpcfail precompile(filterenum, (Function, Type, Vector{ContentSize})) - @warnpcfail precompile(zcumsum, (Vector{Float64},)) - - # These don't work completely but they have partial success - @warnpcfail precompile(repr, (MIME{Symbol("text/plain")}, GridLayout)) +let + while true + bbox = BBox(0, 1000, 0, 1000) + layout = GridLayout(bbox = bbox, alignmode = Outside(0)) + layout2 = GridLayout(1, 1) + layout[1, 1] = layout2 + align_to_bbox!(layout, bbox) + compute_col_row_sizes(1.0, 1.0, layout) + determinedirsize(layout, Row) + trim!(layout) + break + end + nothing end