Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slider with an increment fires action even when value doesn't change #1460

Closed
muellmusik opened this issue May 12, 2015 · 21 comments
Closed
Labels
bug Issues that relate to unexpected/unwanted behavior. Don't use for PRs. comp: Qt GUI sclang Qt components -- for IDE tickets, use "env: SCIDE" instead waiting for information

Comments

@muellmusik
Copy link
Contributor

Try the following:

(
    g = EZSlider(label:" test ", controlSpec:[0, 5, \lin, 1].asSpec);
    g.action_({ |ez| (ez.value.asString ++" is the value of " ++ ez).postln });
);

They slider fires the action repeatedly with the same value before getting to the new one. I think this is a bug, as it makes sense that the action fires only when the value actually changes, or? Or is there a use case for the current behaviour. Not sure if there are similar issues in other widgets.

@muellmusik muellmusik added bug Issues that relate to unexpected/unwanted behavior. Don't use for PRs. comp: Qt GUI sclang Qt components -- for IDE tickets, use "env: SCIDE" instead labels May 12, 2015
@muellmusik
Copy link
Contributor Author

The visual behaviour is also a bit distracting and jerky, at least on OSX 10.10.

@adcxyz
Copy link
Contributor

adcxyz commented May 14, 2015

// does this fix it ? if yes, should also apply for EZKnob and EZRanger.

  • EZSlider {
    valueAction_ { arg val;
    var hasChanged = value != val;
    this.value_(val);
    if (hasChanged) { this.doAction; }
    }
    }

@adcxyz
Copy link
Contributor

adcxyz commented May 15, 2015

come to think of it, maybe it would be best to have a flag for whether
to force the .doAction even if value has not changed ?
this could be a good pattern for all valueAction methods,
regardless of type or spec/non spec:

EZSlider {
   valueAction_ { arg val, force = false;
      var prevVal = value; 
      this.value_(val); // go thru spec.constrain, then compare
      if (force or: { value != prevVal) { this.doAction; } 
   }
}

@telephon
Copy link
Member

On 15.05.2015, at 04:03, Alberto de Campo notifications@github.com wrote:

come to think of it, maybe it would be best to have a flag for checking hasChanged?
this could be a good pattern for all valueAction methods,
regardless of type or spec/non spec:

EZSlider {
valueAction_ { arg val, force = false;
var prevVal = value;
this.value_(val); // go thru spec.constrain, then compare
if (force or: { value != prevVal) { this.doAction; }
}
}

the general idea is that setter methods should only have a single argument, so that x.valueAction = y is always possible.

@muellmusik
Copy link
Contributor Author

Sorry, working to a big deadline now, so haven't tested, but I'm not sure about this as an approach. If I call valueAction explicitly (as one might sometimes do), I'd expect the action to fire.

@adcxyz
Copy link
Contributor

adcxyz commented May 15, 2015

On 15/05/2015, at 18:06 , muellmusik notifications@github.com wrote:Sorry, working to a big deadline now, so haven't tested, but I'm not sure about this as an approach. If I call valueAction explicitly (as one might sometimes do), I'd expect the action to fire.

ok, fair enough.
how about making it a separate method .valueActionIfChanged?
I would think it is useful often enough to merit it that way,

On 15/05/2015, at 16:41 , Julian Rohrhuber notifications@github.com wrote:
the general idea is that setter methods should only have a single argument, so that x.valueAction = y is always possible.

// good point - valueActionIfChanged also gets rid of the flag, so it follows the single-argument pattern:

  • EZSlider {
    valueActionIfChanged_ { arg val;
    var hasChanged = value != val;
    this.value_(val);
    if (hasChanged) { this.doAction; }
    }
    }

BTW, I checked, your example also fires way too often on e.g 3.4.5, so it has likely always been this way.

best adc

@telephon
Copy link
Member

What about this:

+ Function {

    asUpdater { // not quite sure about the name
        var prev;
        { |val|
            if(val != prev) {
                this.value(val);
                prev = val;
            }
        }
    }
}

then you can write:

view.action = { |val|
 <...>
}.asUpdater;


@muellmusik
Copy link
Contributor Author

Not so sure about adding an extra slot to every Function. Are we sure btw, that this shouldn't be handled on the Qt side?

@adcxyz
Copy link
Contributor

adcxyz commented May 17, 2015

On 17/05/2015, at 11:12 , muellmusik notifications@github.com wrote:

Not so sure about adding an extra slot to every Function.

agreed, and I find .valueActionIfChanged expresses the intention quite clearly.
Are we sure btw, that this shouldn't be handled on the Qt side

It does not happen on the Qt side, it happens in .sliderView.action
as soon as the spec does some rounding:

// your example with more posting
g = EZSlider(nil, nil, \test, [1, 10, \lin, 1], {|ez|
"sliderView.value: %\n".postf(ez.sliderView.value);
"ezSlider.value: %\n".postf(ez.value); }
);

// // sliderView action in EZSlider.sc:
//sliderView.action = {
// this.valueAction_(controlSpec.map(sliderView.value));
//};
//
// put an extra post in there - the value does change before mapping
g.sliderView.action = { |slv|
"slView.value before mapping: %\n".postf(slv.value);
g.valueAction_(g.controlSpec.map(slv.value));
};
// but this is filtered with valueActionIfChanged
g.sliderView.action = { |slv|
"slView.value before mapping: %\n".postf(slv.value);
g.valueActionIfChanged_(g.controlSpec.map(slv.value));
};

best, adc

@telephon
Copy link
Member

Is there any agreement over what is the best solution here?

@adcxyz
Copy link
Contributor

adcxyz commented Jun 15, 2015

IMHO, having an extra method called valueActionIfChanged is a very good solution.
It has a clear name stating what it does, and could be added wherever it is useful to have.
valueAction_ exists in 16 classes, all of which are subclasses of either View or EZGui,
so adding valueActionIfChanged to EZGui and View would be sufficient.

[View subclasses] [
    Button
    CheckBox
    EnvelopeView
    ItemViewBase
    Knob
    LevelIndicator
    MultiSliderView
    NumberBox
    Slider
    TextField
]
EZGui.allSubclasses [
    EZKnob
    EZLists
    EZNumber
    EZRanger
    EZScroller
    EZSlider
]

my 2c, adc

@muellmusik
Copy link
Contributor Author

IMHO, having an extra method called valueActionIfChanged is a very good solution.

In principle I agree. At least I can't see how it would cause any problem.

@adcxyz
Copy link
Contributor

adcxyz commented Jun 15, 2015

OK, thanks for getting this out of indecision limbo :-)
So I put this in View and EZGui, and use it in the places where you had the issue
with sliderviews (and numberviews?) firing without value change, yes?

@muellmusik
Copy link
Contributor Author

Yes I think so. Will you do a PR?

On 15 Jun 2015, at 13:04, Alberto de Campo notifications@github.com wrote:

OK, thanks for getting this out of indecision limbo :-)
So I put this in View and EZGui, and use it in the places where you had the issue
with sliderviews (and numberviews?) firing without value change, yes?


Reply to this email directly or view it on GitHub.

@adcxyz
Copy link
Contributor

adcxyz commented Jun 16, 2015

ok, how do I do that? (sorry for git incompetence...)
I tested and committed to my local master, then tried doing pull request in github app,
but cannot send the pull request...

@adcxyz
Copy link
Contributor

adcxyz commented Jun 16, 2015

or is this actually uncontroversial and small enough for just a commit?

@gusano
Copy link
Member

gusano commented Jun 16, 2015

Will you do a PR?

ok, how do I do that? (sorry for git incompetence...)

@adcxyz Alberto, have a look at http://supercollider.github.io/contributing/index.html

To summarize:

  • create a new branch locally
  • commit your changes
  • push them to your fork
  • submit the PR from your github fork page

@muellmusik
Copy link
Contributor Author

You don't need to have a fork even. You can push the branch to the main sc repos, and then do a pull request from there.

@adcxyz
Copy link
Contributor

adcxyz commented Jun 17, 2015

ok, took me a bit to get around to it - here it is.

@telephon
Copy link
Member

Thanks!

@adcxyz
Copy link
Contributor

adcxyz commented Jun 17, 2015

one down, 54 to go ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issues that relate to unexpected/unwanted behavior. Don't use for PRs. comp: Qt GUI sclang Qt components -- for IDE tickets, use "env: SCIDE" instead waiting for information
Projects
None yet
Development

No branches or pull requests

4 participants