You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hello,
First thanks a lot for your work, I have a lot of pleasure using the Makie package!
For a project I needed something like a SliderGrid that would create several IntervalSlider at once and deals with their labels & labelled values. I modified the source code from SliderGrid to a new type IntervalSliderGrid that allows me to do exactly that.
I would argue that it would nice to do it natively but also that a new class should not be added every time a new slider is invented.
How about SliderGrid takes a slidertype option in the namedtuple the user pass it in ?
Say the default would be slidertype=Slider not to break anything but you could also incorporate IntervalSldier or any custom behaviour Slider class in the list of sliders you want to put in your plot.
Here is my code for the IntervalSliderGrid :
using GLMakie
mutable struct IntervalSliderGrid
layout::GridLayout
sliders::Vector{IntervalSlider}
valuelabels::Vector{Label}
labels::Vector{Label}
value_column_width::Observable
end
function IntervalSliderGrid(layout::GridLayout)
new(layout,
IntervalSlider[],
Label[],
Label[],
Observable{Any}(Makie.automatic))
end
function apply_format(value, format::Function)
format(value)
end
function free(sg::IntervalSliderGrid)
foreach(delete!, sg.sliders)
foreach(delete!, sg.valuelabels)
foreach(delete!, sg.labels)
return
end
function initialize_block!(sg::IntervalSliderGrid, nts::NamedTuple...)
default_format(x) = string(x)
default_format(x::AbstractFloat) = string(round(x, sigdigits = 3))
sg.sliders = IntervalSlider[]
sg.valuelabels = Label[]
sg.labels = Label[]
extract_label_range_format(pair::Pair) = pair[1], extract_range_format(pair[2])...
extract_range_format(p::Pair) = (p...,)
extract_range_format(x) = (x, default_format)
for (i, nt) in enumerate(nts)
# Extract key parameters
label = haskey(nt, :label) ? nt.label : ""
range = nt.range
format = haskey(nt, :format) ? nt.format : default_format
startvalues = haskey(nt, :startvalues) ? nt.startvalues : (first(range), last(range))
# Filter out special keys to pass remaining options to IntervalSlider
remaining_pairs = filter(pair -> pair[1] ∉ (:label, :range, :format, :startvalues), pairs(nt))
# Create label
l = Label(sg.layout[i, 1], label, halign = :left)
# Create interval slider with start values
slider = IntervalSlider(sg.layout[i, 2];
range = range,
startvalues = startvalues,
remaining_pairs...)
# Create value label
vl = Label(sg.layout[i, 3],
lift(x -> begin
"$(apply_format(x[1], format)) - $(apply_format(x[2], format))"
end, slider.interval),
halign = :right)
push!(sg.valuelabels, vl)
push!(sg.sliders, slider)
push!(sg.labels, l)
end
# Similar width adjustment logic as original SliderGrid
on(sg.value_column_width) do value_column_width
if value_column_width === Makie.automatic
maxwidth = 0.0
for (slider, valuelabel) in zip(sg.sliders, sg.valuelabels)
# Store initial interval
initial_interval = slider.interval[]
# Test different interval points for label width
a, b = first(slider.range[]), last(slider.range[])
test_intervals = [
(a, a), # Minimum interval
(a, b), # Full range
((a+b)/2, b) # Midpoint to max
]
for test_interval in test_intervals
set_close_to!(slider, test_interval...)
labelwidth = Makie.GridLayoutBase.computedbboxobservable(valuelabel)[].widths[1]
maxwidth = max(maxwidth, labelwidth)
end
# Restore initial interval
set_close_to!(slider, initial_interval...)
end
colsize!(sg.layout, 3, maxwidth)
else
colsize!(sg.layout, 3, value_column_width)
end
end
notify(sg.value_column_width)
return
end`
Notice that the first use-case example is slightly different from the classic one: a layout must be given to initiate IntervalSliderGrid and then passed the NamedTuples instead of directly calling IntervalSliderGrid with a grid position.
This can be changed by using the Block macro to instantiate the IntervalSliderGrid I believe but that was going too far for my needs.
It would be something like this, I assume :
` @block IntervalSliderGrid begin
@forwarded_layout
sliders::Vector{IntervalSlider}
valuelabels::Vector{Label}
labels::Vector{Label}
@attributes begin
"The horizontal alignment of the block in its suggested bounding box."
halign = :center
"The vertical alignment of the block in its suggested bounding box."
valign = :center
"The width setting of the block."
width = Auto()
"The height setting of the block."
height = Auto()
"Controls if the parent layout can adjust to this block's width"
tellwidth::Bool = true
"Controls if the parent layout can adjust to this block's height"
tellheight::Bool = true
"The align mode of the block in its parent GridLayout."
alignmode = Inside()
"The width of the value label column. If `automatic`, the width is determined by sampling a few values from the slider ranges and picking the largest label size found."
value_column_width = Makie.automatic
end
`
I'm giving you this code for people willing to use the IntervalSldierGrid while there is no more general alternative and for inspiration if needed for a new more general implementation. I put the values together on the right side of the slider to make it more similar to the normal slider behaviour in SldierGrid but maybe it's better to have the low value to its left and the upper one to the right. However, this would require to have a different layout for every time you change the slidertype in the grid ?
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Hello,
First thanks a lot for your work, I have a lot of pleasure using the Makie package!
For a project I needed something like a SliderGrid that would create several IntervalSlider at once and deals with their labels & labelled values. I modified the source code from SliderGrid to a new type IntervalSliderGrid that allows me to do exactly that.
I would argue that it would nice to do it natively but also that a new class should not be added every time a new slider is invented.
How about SliderGrid takes a slidertype option in the namedtuple the user pass it in ?
Say the default would be slidertype=Slider not to break anything but you could also incorporate IntervalSldier or any custom behaviour Slider class in the list of sliders you want to put in your plot.
Here is my code for the IntervalSliderGrid :
using GLMakie
Here is a use-case scenario :
`
# Create a layout
fig = Figure()
layout = fig[1, 1] = GridLayout()
# Create IntervalSliderGrid
isg = IntervalSliderGrid(layout)
What I would like to have implemented, would be something like :
` fig = Figure()
isg = IntervalSliderGrid(fig[1,1],
(label="Temperature", range=0.0:100.0, startvalue=20. ),
(label="Pressure", range=1:10, startvalues=(3, 7), slidertype = IntervalSlider)
)
Notice that the first use-case example is slightly different from the classic one: a layout must be given to initiate IntervalSliderGrid and then passed the NamedTuples instead of directly calling IntervalSliderGrid with a grid position.
This can be changed by using the Block macro to instantiate the IntervalSliderGrid I believe but that was going too far for my needs.
It would be something like this, I assume :
`
@block IntervalSliderGrid begin
@forwarded_layout
sliders::Vector{IntervalSlider}
valuelabels::Vector{Label}
labels::Vector{Label}
I'm giving you this code for people willing to use the IntervalSldierGrid while there is no more general alternative and for inspiration if needed for a new more general implementation. I put the values together on the right side of the slider to make it more similar to the normal slider behaviour in SldierGrid but maybe it's better to have the low value to its left and the upper one to the right. However, this would require to have a different layout for every time you change the slidertype in the grid ?
Beta Was this translation helpful? Give feedback.
All reactions