supercollider / supercollider

An audio server, programming language, and IDE for sound synthesis and algorithmic composition.
http://supercollider.github.io
GNU General Public License v3.0
5.42k stars 745 forks source link

NdefGui not resizing vertically #4956

Open madskjeldgaard opened 4 years ago

madskjeldgaard commented 4 years ago

This is in continuation of https://github.com/supercollider/supercollider/issues/4952

Environment

Using SCNvim as the IDE plus:

2020-05-20-175821_1920x1080_scrot

When resizing the GUI's window, it is not responsive, IE the inner objects do not get stretched with the resizing of the window.

This could probably easily be fixed by switching to a LineLayout based gui instead, like in this (EXTREMELY SIMPLIFIED) example:

(
Ndef(\yo, {|freq, amp, pan, what|
    var sig = SinOsc.ar(freq) * amp;

    what;

    Pan2.ar(sig, pan)
}).play;

// Gui function
~ndefgui = {|ndef|
    var window, sliders, transport, play, clear, name, scope, fade, fadeLabel;

    var params = IdentityDictionary.new();
    var paramNames = ndef.controlKeys;

    // Populate param dict
    paramNames.do{|paramname| 
        var spec = Spec.specs.at(paramname);
        spec = if(spec.isNil, { [0.0,1.0].asSpec }, { spec });

        params.put(paramname, spec)
    };

    // GUI
    window = Window.new(ndef.key);
    sliders = [];
    params.keysValuesDo{|pName, spec|

        // Slider
        var slider = Slider.new()
        .orientation_(\horizontal)
        .action_({|obj|
            var sliderVal = obj.value;
            var mappedVal = spec.map(sliderVal);
            valueBox.value = mappedVal;
            ndef.set(pName, mappedVal);
        });

        // Label
        var label = StaticText.new
        .string_(pName);

        // Value box
        var valueBox = NumberBox.new();

        // Slider Layout
        var sliderLayout = HLayout([label, s: 1], [slider, s: 4], [valueBox, s:1]);

        sliders = sliders.add(sliderLayout);
    };

    // Transport
    play = Button.new()
    .states_([
        ["play"], 
        ["stop"]
    ])
    .action_({|obj|
        var val = obj.value;

        if(val==1, {
            ndef.play;
        }, {
            ndef.stop
        })

    });

    // Get current play state
    ndef.isPlaying.if({
        play.value_(1)
    }, {
        play.value_(0)
    });

    clear = Button.new()
    .states_([
        ["clear"]
    ])
    .action_({|obj|
        ndef.clear
    });

    scope = Button.new()
    .states_([
        ["scope"]
    ])
    .action_({|obj|
        ndef.scope
    });

    fadeLabel = StaticText.new()
    .string_("fade:");

    fade = NumberBox.new()
    .step_(0.01)
    .clipLo_(0.0)
    .clipHi_(100.0)
    .action_({|obj|
        var val = obj.value;
        ndef.fadeTime = val;
    });

    transport = HLayout(
        play, clear, scope, fadeLabel, fade 
    );

    window.layout = VLayout([transport, s:1], *sliders);

    window.front;
};

// Make gui
~ndefgui.value(Ndef(\yo));
)

which looks sort of like this:

2020-05-20-180616_1920x1080_scrot

madskjeldgaard commented 4 years ago

@adcxyz you asked me "not responsive while resizing? what do you mean exactly? is it not updating changing values?" on the other issue but I will answer here to maintain order in the chaos that I created :)

What I mean is responsive as in the way web developers talk about responsiveness (but albeit a bit more simply in this case): That gui objects resize with changes to the window size. In this case, I would expect buttons and sliders to resize (like they do when using LineLayouts) to fit whatever screen is used a bit better.

Does that make sense? Thanks!

adcxyz commented 4 years ago

Yes makes sense - was impossible to do well back then... One isue with the new layout scheme is that they assume the guis remain static. But for a NdefMixer or NdefGui, the number of objects may change, number of params, name string lengths etc. Therefore the JITGuis were designed for regular, easy to read layout; maximum information for minimal screen real estate. If every button/nametag renegotiates its size when string lengths change, it becomes difficult to make layouts where you have 8 JITGuis laid out to see everything at once.

telephon commented 4 years ago

Isn't it very easy in the new scheme to add and remove items from a gui?

x = VLayout();
w = Window.new(bounds:Rect(100,100,300,80)).layout_(x).front;
y = { Slider.new } ! 16;
y.do(x.add(_));

y.choose.remove
y.choose.remove
y.choose.remove
eleses commented 4 years ago

I regularly use EnvirGui in semi-resizable fashion in the new layouts. "Semi-resizable" means that it only resizes horizontally, i.e. the length of sliders. Vertical resizing is indeed not baked into the internal logic of EnvirGui, with the fixed number of slots.

Substantially related since NdegGui & EnvirGui use those EZ things #1685 and those don't resize vertically either, i.e. not only is the number of slots fixed in JITGui's (because of their own internal design) but also their inner elements don't resize vertically because the EZ things don't.

It's actually debatable how JITGuis or any such "group-of-sliders GUIs" should respond to vertical resizing notifications. madskjeldgaard propose above that the gap between elements be increased. Resizing the slider elements themselves is also an option. In fact, this is the approach taken by MView. I think that in order to make everyone happy, choosing whether the gaps are resizable or the sliders themselves are resizable (or both) should be an option, i.e. tweakable knob in such group-of-sliders GUIs... Note how in VLayout one can specify both fixed (pixel-sized) gaps or stretchable ones. (But of course JITGui is not using VLayout.)

And there's actually a 3rd way in which such "group-of-sliders GUIs" could respond to vertical resize: by popping more (or fewer) sliders into the view when the underlying object has more "items" than fit in the current view. The JITguis have a fixed-number-of-slots approach and thus use a scroll bar if there are more items in the data-object being viewed than the gui is configured for. And this ends up looking silly when you resize the JITgui so it would have enough space to show all its elements, but instead you get empty space and the scroll stays. So, arguably, a dynamic number of slots could be another option for how such GUIs respond to resize, and this also should probably a user-configurable aspect. (You get this "out of the box" with TreeView, which is why I'm hoping to do an EnvirGui "v2" based on TreeView; TreeView also provides sorting from the "table" hearders and the ability to add grouping by using extra columns, thus giving/borrowing a slider-sub-group feature that VarGui has, albeit perhaps not as neatly rendered [no easy way to get gaps marking the sub-groups in TreeView], but one could still use colors or the actual indentation features of TreeView for sub-items.)

@brianlheim A better title here might be "NdefGui not resizing vertically" or "not stretching its internal elements in response to resize" (its view area does resize, but just with "empty space"). There's nothing "unresponsive" about NdefGui otherwise being discussed here, as far as I can tell. Also, the issue is shared by all JITGui's (e.g. including EnvirGui, PdefGui etc.), so the ticket might be broadened in that respect. (N.B. this report is more like a feature request to me...)