# GLMakie Menu() maximum number of items?

**URL:** <https://discourse.julialang.org/t/glmakie-menu-maximum-number-of-items/82948>\
**Category:** Visualization\
**Created:** [June 18, 2022, 1:20am UTC](https://discourse.julialang.org/t/glmakie-menu-maximum-number-of-items/82948 "2022-06-18T01:20:03Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![garrek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/garrek/32/27937_2.png) [@garrek](https://discourse.julialang.org/u/garrek)\
**Post date:** [June 18, 2022, 1:20am UTC](https://discourse.julialang.org/t/glmakie-menu-maximum-number-of-items/82948/1 "2022-06-18T01:20:03Z")

</div>

Is there a maximum number of items that can be added to a Menu? I’m experimenting with GLMakie and `Observable`s. My program watches a folder for new files. Both the data and Menu `options` are `Observable`s, so when a new file appears it is plotted and a new item is added to the Menu `options` so a user can select this and all previous data. My code works, but crashes whenever I add a 7th item. I’m having difficulty parsing the error message, but my first guess is that there is some upper limit to the number of items a Menu can have based on the GLMakie screen size or something?

```julia
julia> GUIMakie.run("./data/")
New file: notworking.lvm
New file: sig_220607_121211.lvm
New file: sig_220607_154155.lvm
New file: sig_220607_174053.lvm
New file: sig_220607_174239.lvm
New file: three_stacks.lvm
New file: two_stacks_noxdata.lvm
ERROR: InexactError: trunc(UInt8, 256)
Stacktrace:
  [1] throw_inexacterror(f::Symbol, #unused#::Type{UInt8}, val::Int64)
    @ Core ./boot.jl:612
  [2] checked_trunc_uint
    @ ./boot.jl:642 [inlined]
  [3] toUInt8
    @ ./boot.jl:704 [inlined]
  [4] UInt8
    @ ./boot.jl:764 [inlined]
  [5] convert
    @ ./number.jl:7 [inlined]
  [6] cvt1
    @ ./essentials.jl:343 [inlined]
  [7] ntuple
    @ ./ntuple.jl:49 [inlined]
  [8] convert
    @ ./essentials.jl:344 [inlined]
  [9] push!
    @ ./array.jl:994 [inlined]
 [10] #117
    @ ~/.julia/packages/GLMakie/SJcSR/src/screen.jl:259 [inlined]
 [11] get!(default::GLMakie.var"#117#119"{GLMakie.Screen, Makie.Scene}, h::Dict{WeakRef, UInt8}, key::WeakRef)
    @ Base ./dict.jl:464
 [12] push!(screen::GLMakie.Screen, scene::Makie.Scene, robj::GLMakie.GLAbstraction.RenderObject{GLMakie.GLAbstraction.StandardPrerender})
    @ GLMakie ~/.julia/packages/GLMakie/SJcSR/src/screen.jl:257
 [13] cached_robj!(robj_func::GLMakie.var"#245#246"{Makie.Scene, MakieCore.Mesh{Tuple{GeometryBasics.Mesh{2, Float32, GeometryBasics.Ngon{2, Float32, 3, GeometryBasics.Point{2, Float32}}, GeometryBasics.SimpleFaceView{2, Float32, 3, GeometryBasics.OffsetInteger{-1, UInt32}, GeometryBasics.Point{2, Float32}, GeometryBasics.NgonFace{3, GeometryBasics.OffsetInteger{-1, UInt32}}}}}}}, screen::GLMakie.Screen, scene::Makie.Scene, x::MakieCore.Mesh{Tuple{GeometryBasics.Mesh{2, Float32, GeometryBasics.Ngon{2, Float32, 3, GeometryBasics.Point{2, Float32}}, GeometryBasics.SimpleFaceView{2, Float32, 3, GeometryBasics.OffsetInteger{-1, UInt32}, GeometryBasics.Point{2, Float32}, GeometryBasics.NgonFace{3, GeometryBasics.OffsetInteger{-1, UInt32}}}}}})
    @ GLMakie ~/.julia/packages/GLMakie/SJcSR/src/drawing_primitives.jl:113
 [14] draw_atomic
    @ ~/.julia/packages/GLMakie/SJcSR/src/drawing_primitives.jl:493 [inlined]
 [15] insert!
    @ ~/.julia/packages/GLMakie/SJcSR/src/drawing_primitives.jl:121 [inlined]
 [16] (::GLMakie.var"#177#178"{GLMakie.Screen, Makie.Scene})(x::MakieCore.Mesh{Tuple{GeometryBasics.Mesh{2, Float32, GeometryBasics.Ngon{2, Float32, 3, GeometryBasics.Point{2, Float32}}, GeometryBasics.SimpleFaceView{2, Float32, 3, GeometryBasics.OffsetInteger{-1, UInt32}, GeometryBasics.Point{2, Float32}, GeometryBasics.NgonFace{3, GeometryBasics.OffsetInteger{-1, UInt32}}}}}})
    @ GLMakie ~/.julia/packages/GLMakie/SJcSR/src/drawing_primitives.jl:126
 [17] foreach(f::GLMakie.var"#177#178"{GLMakie.Screen, Makie.Scene}, itr::Vector{MakieCore.AbstractPlot})
    @ Base ./abstractarray.jl:2712
 [18] insert!
    @ ~/.julia/packages/GLMakie/SJcSR/src/drawing_primitives.jl:123 [inlined]
 [19] (::GLMakie.var"#177#178"{GLMakie.Screen, Makie.Scene})(x::MakieCore.Mesh{Tuple{Vector{GeometryBasics.Mesh{2, Float32, GeometryBasics.Ngon{2, Float32, 3, GeometryBasics.Point{2, Float32}}, GeometryBasics.SimpleFaceView{2, Float32, 3, GeometryBasics.OffsetInteger{-1, UInt32}, GeometryBasics.Point{2, Float32}, GeometryBasics.NgonFace{3, GeometryBasics.OffsetInteger{-1, UInt32}}}}}}})
    @ GLMakie ~/.julia/packages/GLMakie/SJcSR/src/drawing_primitives.jl:126
 [20] foreach(f::GLMakie.var"#177#178"{GLMakie.Screen, Makie.Scene}, itr::Vector{MakieCore.AbstractPlot})
    @ Base ./abstractarray.jl:2712
 [21] insert!(screen::GLMakie.Screen, scene::Makie.Scene, x::MakieCore.Combined)
    @ GLMakie ~/.julia/packages/GLMakie/SJcSR/src/drawing_primitives.jl:123
 [22] push!(scene::Makie.Scene, plot::MakieCore.Combined{Makie.poly, Tuple{Vector{Vector{GeometryBasics.Point{2, Float32}}}}})
    @ Makie ~/.julia/packages/Makie/Ws9gB/src/scenes.jl:409
 [23] plot!(scene::Makie.Scene, P::Type{MakieCore.Combined{Makie.poly, Tuple{GeometryBasics.HyperRectangle{2, Int64}}}}, attributes::MakieCore.Attributes, input::Tuple{Observables.Observable{GeometryBasics.HyperRectangle{2, Int64}}}, args::Observables.Observable{Tuple{Vector{Vector{GeometryBasics.Point{2, Float32}}}}})
    @ Makie ~/.julia/packages/Makie/Ws9gB/src/interfaces.jl:403
 [24] plot!(scene::Makie.Scene, P::Type{MakieCore.Combined{Makie.poly}}, attributes::MakieCore.Attributes, args::Observables.Observable{GeometryBasics.HyperRectangle{2, Int64}}; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Makie ~/.julia/packages/Makie/Ws9gB/src/interfaces.jl:320
 [25] plot!
    @ ~/.julia/packages/Makie/Ws9gB/src/interfaces.jl:288 [inlined]
 [26] #plot!#132
    @ ~/.julia/packages/Makie/Ws9gB/src/interfaces.jl:271 [inlined]
 [27] poly!(::Makie.Scene, ::Vararg{Any}; attributes::Base.Pairs{Symbol, Any, NTuple{5, Symbol}, NamedTuple{(:color, :visible, :strokecolor, :strokewidth, :inspectable), Tuple{Observables.Observable{Any}, Observables.Observable{Any}, Observables.Observable{ColorTypes.RGB{Float32}}, Observables.Observable{Any}, Bool}}})
    @ Makie ~/.julia/packages/MakieCore/C4HO7/src/recipes.jl:37
 [28] initialize_block!(box::Makie.Box)
    @ Makie ~/.julia/packages/Makie/Ws9gB/src/makielayout/blocks/box.jl:11
 [29] _block(::Type{Makie.Box}, ::Makie.Scene; bbox::Nothing, kwargs::Base.Pairs{Symbol, Any, NTuple{5, Symbol}, NamedTuple{(:width, :height, :color, :strokewidth, :visible), Tuple{Nothing, Nothing, ColorTypes.RGB{Float32}, Int64, Observables.Observable{Any}}}})
    @ Makie ~/.julia/packages/Makie/Ws9gB/src/makielayout/blocks.jl:393
 [30] #_#996
    @ ~/.julia/packages/Makie/Ws9gB/src/makielayout/blocks.jl:269 [inlined]
 [31] _reassemble_menu(m::Makie.Menu, scene::Makie.Scene, selectionrect::Makie.Box, selectiontext::Makie.Label, allrects::Vector{Makie.Box}, alltexts::Vector{Makie.Label}, mouseeventhandles::Vector{Makie.MouseEventHandle}, contentgrid::GridLayoutBase.GridLayout, optionstrings::Base.RefValue{Vector{String}})
    @ Makie ~/.julia/packages/Makie/Ws9gB/src/makielayout/blocks/menu.jl:251
 [32] (::Makie.var"#1667#1679"{Makie.Menu, Vector{Makie.MouseEventHandle}, Vector{Makie.Label}, Vector{Makie.Box}, Makie.Label, Observables.Observable{String}, Base.RefValue{Vector{String}}, Makie.Box, GridLayoutBase.GridLayout, Makie.Scene})(options::Vector{String})
    @ Makie ~/.julia/packages/Makie/Ws9gB/src/makielayout/blocks/menu.jl:116
 [33] #invokelatest#2
    @ ./essentials.jl:716 [inlined]
 [34] invokelatest
    @ ./essentials.jl:714 [inlined]
 [35] notify
    @ ~/.julia/packages/Observables/ynr7h/src/Observables.jl:143 [inlined]
 [36] setindex!(observable::Observables.Observable, val::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:86
 [37] #15
    @ ~/.julia/packages/Observables/ynr7h/src/Observables.jl:393 [inlined]
 [38] (::Observables.var"#callback#13"{Observables.var"#15#16"{Makie.var"#1009#1010"{DataType}, Observables.Observable{Any}}, Tuple{Observables.Observable{Vector{String}}}})(x::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:339
 [39] #invokelatest#2
    @ ./essentials.jl:716 [inlined]
 [40] invokelatest
    @ ./essentials.jl:714 [inlined]
 [41] notify
    @ ~/.julia/packages/Observables/ynr7h/src/Observables.jl:143 [inlined]
 [42] setindex!(observable::Observables.Observable, val::Any)
    @ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:86
 [43] run(datadir::String, extension::String)
    @ GUIMakie ~/Documents/projects/GUIMakie/src/gui.jl:90
 [44] run(datadir::String)
    @ GUIMakie ~/Documents/projects/GUIMakie/src/gui.jl:32
 [45] top-level scope
    @ REPL[3]:1

```

 ![Screen Shot 2022-06-18 at 10.12.34](https://global.discourse-cdn.com/julialang/original/3X/4/5/45aed64e0b91e2eef7d214ac09e1d40af80ea204.png)

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [June 18, 2022, 4:44am UTC](https://discourse.julialang.org/t/glmakie-menu-maximum-number-of-items/82948/2 "2022-06-18T04:44:53Z")

</div>

In the last refactor each Block got its own container scene and Menu uses Labels and Boxes internally which is now rather inefficient. That’s why you hit the 255 relatively quickly. I need to rewrite menu so it uses only one poly and one text object I think

---

<div class="post-metadata">

**Author:** ![garrek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/garrek/32/27937_2.png) [@garrek](https://discourse.julialang.org/u/garrek)\
**Post date:** [June 18, 2022, 4:51am UTC](https://discourse.julialang.org/t/glmakie-menu-maximum-number-of-items/82948/3 "2022-06-18T04:51:21Z")

</div>

I see, that makes sense. Also explains why it gets slow very quickly. For the record, I made a version of this with only one Menu and I’m able to add many more plots (I’ve tested with 14 so far) without it crashing. But Menu gets very slow when switching between plots with this many.

I think what I’ll do for now is decide a limit and boot the oldest plots from the Menu.

(Second example with a live-updating plot (right) and a plot connected to the menu (left)

 ![Screen Shot 2022-06-18 at 13.49.37](https://global.discourse-cdn.com/julialang/original/3X/5/8/58ff97aa50c16c7a8ef0a673d5b6b6373d31bf97.png)

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [June 18, 2022, 4:52am UTC](https://discourse.julialang.org/t/glmakie-menu-maximum-number-of-items/82948/4 "2022-06-18T04:52:44Z")

</div>

Yes the code for menu was written rather quickly as a proof of concept at the time and didn’t pay much attention to performance, so an overhaul is much needed

---

<div class="post-metadata">

**Author:** ![garrek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/garrek/32/27937_2.png) [@garrek](https://discourse.julialang.org/u/garrek)\
**Post date:** [June 18, 2022, 4:59am UTC](https://discourse.julialang.org/t/glmakie-menu-maximum-number-of-items/82948/5 "2022-06-18T04:59:41Z")

</div>

I should have checked the Issues. There is one from just a few weeks ago on this very topic: [Issue #2013](https://github.com/JuliaPlots/Makie.jl/issues/2013)

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [June 19, 2022, 6:31pm UTC](https://discourse.julialang.org/t/glmakie-menu-maximum-number-of-items/82948/6 "2022-06-19T18:31:50Z")

</div>

Can you try with Makie 0.17.7 that is being released right this second? It should work much better for large menus.

---

<div class="post-metadata">

**Author:** ![garrek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/garrek/32/27937_2.png) [@garrek](https://discourse.julialang.org/u/garrek)\
**Post date:** [June 20, 2022, 12:18am UTC](https://discourse.julialang.org/t/glmakie-menu-maximum-number-of-items/82948/7 "2022-06-20T00:18:01Z")

</div>

Yeah, the update significantly speeds up menus. I tried both the two-panel figure and four-panel figure again. I added 10 plots and the “live” plot updates faster, so I guess the lag between adding a file and updating the plot was because Menu was taking a while as it got larger. Switching between plots is much faster now even at 10 plots in the menu. The four-panel figure no longer crashes.

I notice two slight problem areas:

1. Sometimes the menu doesn’t register a click. I’m not sure if that’s because there’s a time lag after a selection is made before another selection can be made or it’s just not registering some clicks. The non-registering clicks occur both for opening the menu and making a selection and happens even for a small menu (3 items).

2. When an open menu covers a plot, clicks will sometimes manipulate the plot instead of registering as a menu click.

This behavior is pretty inconsistent. Sometimes menu is smooth and registers almost all clicks correctly. Sometimes it doesn’t register several clicks in a row or two or three clicks will register on the plot behind menu. Here’s an animation:

![Menu demo in Makie 0.17.7](https://global.discourse-cdn.com/julialang/original/3X/2/e/2eea2c08e5cfdc710ac0e191f816cec7175ca012.gif)

I also notice a new bug with DataInspector. Did something change with how that should be initiated? I tried a minimal example and it still errors.

```julia
fig = Figure
ax = Axis([fig[1, 1])
lines!(ax, rand(10), rand(10))
inspector = DataInspector(fig)

```

Error message:

```julia
**ERROR:** type Array has no field extents
Stacktrace:
[1] **getproperty**
@ ./Base.jl:42 [inlined]
[2] **Bbox_from_glyphcollection(**text::String, gc::Vector{Point{2, Float32}}**)**
@ Makie ~/.julia/packages/Makie/fJ4OE/src/interaction/inspector.jl:191
[3] **(::Makie.var"#883#886"{Observable{Any}})(**gc::Vector{Point{2, Float32}}, pos::Point{2, Float32}, pad::Vec{4, Float32}**)**
@ Makie ~/.julia/packages/Makie/fJ4OE/src/interaction/inspector.jl:294
[4] **#map#19**
@ ~/.julia/packages/Observables/ynr7h/src/Observables.jl:444 [inlined]
[5] **map(**::Makie.var"#883#886"{Observable{Any}}, ::Observable{Vector{Point{2, Float32}}}, ::Observable{Any}, ::Observable{Any}**)**
@ Observables ~/.julia/packages/Observables/ynr7h/src/Observables.jl:444
[6] **plot!(**plot::Combined{Makie._inspector, Tuple{Int64}}**)**
@ Makie ~/.julia/packages/Makie/fJ4OE/src/interaction/inspector.jl:293
[7] **plot!(**scene::Scene, P::Type{Combined{Makie._inspector, Tuple{Int64}}}, attributes::Attributes, input::Tuple{Observable{Int64}}, args::Observable{Tuple{Int64}}**)**
@ Makie ~/.julia/packages/Makie/fJ4OE/src/interfaces.jl:402
[8] **plot!(**scene::Scene, P::Type{Combined{Makie._inspector}}, attributes::Attributes, args::Int64; kw_attributes::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}**)**
@ Makie ~/.julia/packages/Makie/fJ4OE/src/interfaces.jl:320
[9] **plot!**
@ ~/.julia/packages/Makie/fJ4OE/src/interfaces.jl:288 [inlined]
[10] **#plot!#132**
@ ~/.julia/packages/Makie/fJ4OE/src/interfaces.jl:271 [inlined]
[11] **_inspector!(**::Scene, ::Vararg{Any}; attributes::Base.Pairs{Symbol, Observable{StaticArrays.SMatrix{4, 4, Float32, 16}}, Tuple{Symbol}, NamedTuple{(:_root_px_projection,), Tuple{Observable{StaticArrays.SMatrix{4, 4, Float32, 16}}}}}**)**
@ Makie ~/.julia/packages/MakieCore/4Hq26/src/recipes.jl:37
[12] **DataInspector(**scene::Scene; priority::Int64, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}**)**
@ Makie ~/.julia/packages/Makie/fJ4OE/src/interaction/inspector.jl:442
[13] **DataInspector**
@ ~/.julia/packages/Makie/fJ4OE/src/interaction/inspector.jl:439 [inlined]
[14] **#DataInspector#889**
@ ~/.julia/packages/Makie/fJ4OE/src/interaction/inspector.jl:435 [inlined]
[15] **DataInspector(**fig_or_block::Figure**)**
@ Makie ~/.julia/packages/Makie/fJ4OE/src/interaction/inspector.jl:435
[16] top-level scope
@ REPL[11]:1

```
