Button too smart for it's own good?


#1

I am trying to use a plain juce::Button with nothing fancy. No notification no listeners, just my own subclass.

I call setToggleState with sendChangeNotification = false but yet, I am still getting the button trying to “click itself”.

Specifically:

void Button::setToggleState (const bool shouldBeOn,
                             const bool sendChangeNotification)
{
    if (shouldBeOn != lastToggleState)
    {
        if (isOn != shouldBeOn)  // this test means that if the value is void rather than explicitly set to
            isOn = shouldBeOn;   // false, it won't be changed unless the required value is true.

        lastToggleState = shouldBeOn;

Since the Button listens to its own Value object (isOn), it later receives valueChanged and then calls sendClickMessage(). This is screwing me up.

How do I get a POB (Plain Old Button) again?


#2

But if you set the toggle state to e.g. ‘true’, then when the valueChanged() callback happens, it will again call setToggleState (true), which will be ignored because lastToggleState is already true (??)


#3

You would think that, but sometimes true != true (according to Visual Studio 2008):

[attachment=0]vs2008bug.jpg[/attachment]

I am going to see about working around the bit field member and see if that’s the problem.


#4

Jules how did you accomplish this? I feel like my skills will never catch up to yours…

[attachment=0]vs2008bug2.jpg[/attachment]


#5

Don’t forget to scroll to the bottom of each image…


#6

This is the problem right here:
[attachment=0]vs2008bug3.jpg[/attachment]


#7

I think you’re getting confused by a recursive callback. when isOn = shouldBeOn is called, it’s probably recursively calling setToggleState with a new parameter…?


#8

I don’t know how the hell this is happening, but the vs2008 debugger shows both bool values as true, but yet the comparison is considering them not equal.

Check it out:

[attachment=0]vs2008bug4.jpg[/attachment]

Explain how “copyOfShouldBeOn != copyOfToggleState” evaluates to true??

The yellow arrow is where I have a break in the debugger, and the Watch shows the values of the 4 variables in question.


#9

Ok… That does seem to defy the laws of physics!


#10

Phew…it seems like an uninitialized variable and not a compiler bug. I am continuing to try to figure it out:

[attachment=0]vs2008bug5.jpg[/attachment]


#11

I was calling setToggleState() with an uninitialized bool, and that was causing all the trouble! Not that I intentionally uninitialized it…it’s just that I am also using async updaters for some of my own controls and the juce Button got its async updater (for the juce::Value) to execute before mine - completely unexpected behavior as I did not realize what Button was doing with its toggle state.

This fixes it in the Button code although clearly I need to fix my code to account for the order of async updating

void Button::setToggleState (bool shouldBeOn,
                             const bool sendChangeNotification)
{
    if (shouldBeOn) // fix shouldBeOn if its uninitialized
      shouldBeOn = true;
    else
      shouldBeOn = false;
//...

#12

Wow - that’s an evil bug to track down!