Cabbage Logo
Back to Cabbage Site

Setting a minimum difference in range-slider?

Let’s say you have a hrange-slider, left starts with 0 and the right starts with 1.

It would be nice if it was possible to set a minimum difference (say 0.1) so that if you slide one of the thumbs very close to the other, and the difference between them is 0.1, the whole slider would drag along as it does when you grab the middle of it.

Is there any way to do this?

Hmm, you could do this with a custom range slider that hides two regular sliders. To do it with a regular range slider you could check to see which thumb is moving and then update the position of the other one accordingly :thinking:

Seems like this is not possible? or am I doing something wrong perhaps?

<Cabbage>
form caption("Untitled") size(400, 300), guiMode("queue") pluginId("def1")
rslider bounds(296, 162, 100, 100), channel("gain"), range(0, 1, 0, 1, .01), text("Gain"), trackerColour("lime"), outlineColour(0, 0, 0, 50), textColour("black")
hrange bounds(106, 64, 250, 40) channel("rangesliderMin10001", "rangesliderMax10001") max(1) min(0) range(0, 1, 0:1, 1, 0.001)
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1


instr 1

kGain cabbageGetValue "gain"
cabbageSetValue "rangesliderMin10001", kGain

endin

</CsInstruments>
<CsScore>
;causes Csound to run for about 7000 years...
f0 z
;starts instrument 1 and runs it for a week
i1 0 [60*60*24*7] 
</CsScore>
</CsoundSynthesizer>

Setting this requires a little extra work. I don’t think we can directly manipulate the channel just yet, so in the mean time you need to do something like this (see below). So you need to set minValue/maxValue, with the first channel passed to the slider. I know it’s ugly. I really need to revisit that code!

<Cabbage>
form caption("Untitled") size(400, 300), guiMode("queue") pluginId("def1")
rslider bounds(296, 162, 100, 100), channel("gain"), range(0, 1, 0, 1, .01), text("Gain"), trackerColour("lime"), outlineColour(0, 0, 0, 50), textColour("black")
hrange bounds(106, 64, 250, 40) channel("rangesliderMin", "rangesliderMax") max(1) min(0) range(0, 1, 0:1, 1, 0.001)
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1


instr 1
    kGain, kTrig cabbageGetValue "gain"
    cabbageSet kTrig, "rangesliderMin", "minValue", kGain
endin

</CsInstruments>
<CsScore>
;causes Csound to run for about 7000 years...
f0 z
;starts instrument 1 and runs it for a week
i1 0 [60*60*24*7] 
</CsScore>
</CsoundSynthesizer>

Hmm, I can’t seem to figure out a way to do this with the normal range-sliders.

I think I would not be able to achieve what I’m trying to do with two normal hsliders, because they would have to be placed with a height difference, while what I’m trying to do is have the thumbs at the same height-level, which I know how to achieve with the range-slider.

<Cabbage>
form caption("Untitled") size(400, 300), guiMode("queue") pluginId("def1")
hrange bounds(78, 120, 250, 40) channel("rangesliderMin", "rangesliderMax") max(1) min(0) range(0, 1, 0:1, 1, 0.001)
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1

instr 1

    kRangeMin, kRangeMin_Trig cabbageGetValue "rangesliderMin"
    kRangeMax, kRangeMax_Trig cabbageGetValue "rangesliderMax"
    
    if changed2(kRangeMin) == 1 then
        if (kRangeMax - kRangeMin) >= 0.1 then
            cabbageSet  "rangesliderMax", "maxValue", (kRangeMax - kRangeMin) + 0.1
        endif
    endif
    
    printk2 (kRangeMax - kRangeMin) + 0.1
endin
</CsInstruments>
<CsScore>
;causes Csound to run for about 7000 years...
f0 z
;starts instrument 1 and runs it for a week
i1 0 [60*60*24*7] 
</CsScore>
</CsoundSynthesizer>

Any tips? :smiley:

A few issues, the most obvious one being that you are using an i-rate version of cabbageSet… try this one:

instr 1

    kRangeMin, kRangeMin_Trig cabbageGetValue "rangesliderMin"
    kRangeMax, kRangeMax_Trig cabbageGetValue "rangesliderMax"
    
    if changed2(kRangeMin) == 1 then
        if (kRangeMax - kRangeMin) <= 0.1 then
            cabbageSet 1, "rangesliderMin", "maxValue", kRangeMin + 0.1
        endif
    endif

endin

Nice one, thank you :sunglasses:

So now it works quite nicely, but there is some strangeness happening when you adjust the range all the way on both sides :thinking: Is there any way to avoid this?

<Cabbage>
form caption("Untitled") size(400, 300), guiMode("queue") pluginId("def1")
hrange bounds(78, 120, 250, 40) channel("rangesliderMin", "rangesliderMax") max(1) min(0) range(0, 1, 0:1, 1, 0.001)
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1

instr 1

    kRangeMin, kRangeMin_Trig cabbageGetValue "rangesliderMin"
    kRangeMax, kRangeMax_Trig cabbageGetValue "rangesliderMax"

    if (kRangeMax - kRangeMin) <= 0.1 then
        cabbageSet 1, "rangesliderMin", "maxValue", kRangeMin + 0.1
        cabbageSet 1, "rangesliderMin", "minValue", kRangeMax - 0.1
    endif
  
endin
</CsInstruments>
<CsScore>
;causes Csound to run for about 7000 years...
f0 z
;starts instrument 1 and runs it for a week
i1 0 [60*60*24*7] 
</CsScore>
</CsoundSynthesizer>

You could do something like this, and prevent the auto-updates from happening towards the very ends?

instr 1

    kRangeMin, kRangeMin_Trig cabbageGetValue "rangesliderMin"
    kRangeMax, kRangeMax_Trig cabbageGetValue "rangesliderMax"

    if (kRangeMax - kRangeMin) <= 0.1 && (kRangeMin<.9) then 
        cabbageSet 1, "rangesliderMin", "maxValue", kRangeMin + 0.1
        cabbageSet 1, "rangesliderMin", "minValue", kRangeMax - 0.1
    endif
  
endin

I guess it kinda works, but doesn’t it visually look really wonky?

Yeah, the jump is a little jarring. But can’t you scale the difference depending on the position? So instead of it always being 0.1, it might say start at 0 at the outer edges and moves towards 0.1? :thinking:

Yes, something like that could work. The issue is though that I’m changing the bounds of a widget with range-sliders, and right now, the bounds are about pixel-perfect with the range-sliders thumbs. The purpose for limiting the range-slider difference is that you can’t adjust the widgets bounds to look non-existent (0 width, 0 height) or generally with a extremely short height or width. Wouldn’t this suggestion throw the “pixel-perfect” adjustment somewhat off?

I think you’ll need to try a few things. Maybe this won’t work, but it might lead to a solution :slight_smile: