Button InstantToggle


#1

The normal behaviour for the buttons on a mixer are to instantly switch modes when clicked… with the current Button behaviour we have setTriggeredOnMouseDown() to instantly trigger on the mouseDown() but the buttons still redraw and react to the mouseUp()

I have made these changes to the Button class for your consideration:

In juceButton.h add:

    /** Sets whether the button should be instantly toggled when clicked.
     
        Only works when setTriggeredOnMouseDown is true.
     */
    void setInstantToggleMode(bool isInstantlyToggledOnClick) noexcept;

and

bool instantToggle : 1;

in juceButton.cpp I added:

Button::Button (const String& name)
  : Component (name),
    text (name),
    buttonPressTime (0),
    lastRepeatTime (0),
    commandManagerToUse (nullptr),
    autoRepeatDelay (-1),
    autoRepeatSpeed (0),
    autoRepeatMinimumDelay (-1),
    radioGroupId (0),
    commandID (0),
    connectedEdgeFlags (0),
    buttonState (buttonNormal),
    lastToggleState (false),
    clickTogglesState (false),
    needsToRelease (false),
    needsRepainting (false),
    isKeyDown (false),
    triggerOnMouseDown (false),
    generateTooltip (false),
    instantToggle(false)
{
    setWantsKeyboardFocus (true);
    isOn.addListener (this);
}
void Button::setInstantToggleMode(bool isInstantlyToggledOnClick) noexcept
{
    instantToggle = isInstantlyToggledOnClick;
}

and

void Button::mouseDown (const MouseEvent& e)
{
    updateState (true, true);

    if (isDown())
    {
        if (autoRepeatDelay >= 0)
            getRepeatTimer().startTimer (autoRepeatDelay);

        if (triggerOnMouseDown)
            internalClickCallback (e.mods);
    
        if (instantToggle && triggerOnMouseDown)
            mouseUp(e);
    }
}

Cheers,

Rail


#2

It’s a perfectly valid idea, but I just can’t add yet another subtle behavioural option to the already-bloated Button class!

I’d consider suggestions for simplifications/refactorings of the Button class’s functionality that would enable new behaviours like this, but not single-purpose additions like this, sorry!


#3

The only reason I couldn’t subclass Button for this was because mouseDown() isn’t virtual (if that’s an option you’d entertain :wink: )

Otherwise I’ll just make a note to add these changes every time I update my copy of JUCE.

Just thought your user base seems audio-centic and the addition made sense for more folks than just moi.

Cheers,

Rail


#4

Really??

I’m getting really bored of explaining this mistake to people. It must be the most common C++ misunderstanding we see on the forum.

Any overridden virtual method is always virtual, it doesn’t need to be marked with the keyword.


#5

Sorry, it was 4 in the morning… I forgot that Button was a Component… working on very little sleep here…

Cheers,

Rail


#6

The design and refactoring of user interface classes is a hard problem. To date, there has never been an elegant system designed that addresses all use-cases. JUCE does a fairly good job, especially with the Component base class interface. But it is showing signs of age.

Button classes are so simple, that discussions on a proper refactoring are academic at best. Button implementations are trivial to write, and if you want a custom JUCE button behavior it is a straightforward process to make a duplicate of the juce::Button and modify it to suit your needs. When it comes to user interface classes, you often need to compromise principles such as DRY.

The interesting part of juce::Button is in the handling of keyboard shortcuts and command messages. In my opinion, only this part needs to be refactored. Ideally it would be some sort of reusable class that can be leveraged to give keyboard shortcut / command support to any custom control not just buttons. As for the actual mouse down / tracking of the button, that is far too simple to justify making changes for.

Other JUCE interface classes are much more deserving of a refactoring. Slider should definitely be broken up into individual separate components: SliderEdit, SliderThumb come to mind. The actual Slider class could be replaced by a composite Component that creates child edit and thumb objects hooked together using a ComponentBroadcast facility.

ListBox and TableListBox could also use some spring cleaning, along with the menus.


#7

Can’t disagree with any of that, Vinnie!