-
Notifications
You must be signed in to change notification settings - Fork 12
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
how to disable input listeners #1041
Comments
How about adding the ability to disable listeners? We could add |
Over in phetsims/ph-scale#118, ph-scale design team decided that they want to move forward with this. I'll discuss with @jonathanolson. |
@jonathanolson The proposal is to add |
@pixelzoom - My understanding from the meeting was to add it to the dragListener, but I didn't think it was to add it to all the listeners - since button presses don't need it for instance? |
@kathy-phet That was not my understanding from the design meeting, and doesn't match my meeting notes in phetsims/ph-scale#118 (comment). Making this feature specific to drag listeners is also something that I do not agree with. We are not trying to solve only the dropper button problem in ph-scale. This is a general issue that could occur for any input listener. And DragListener is a subclass of PressListener, so whatever is done for drag listeners should be applicable to buttons (which use PressListener). So I think we should first investigate how this would be done uniformly for input listeners. |
Only instrumented input listeners (e.g. SimpleDragHandler, PressListener variants, etc.), or ALL input listeners (e.g. Presumably changing enabled to false would do the equivalent of interrupting the listener? How would "enabled" false work for hover state? |
Time estimate for SimpleDragHandler/PressListener wouldn't be too long, as long as the behavior is well defined. It will probably take longer to hook it up everywhere (as sun buttons or other things have their own "enabled" Properties, and it's unclear if we would want to tie those together). |
Yes.
I don't know, mainly because I don't really understand the question. While the immediate need for this is for drag listeners, I recommend doing this generally for input listeners, rather than just for drag listeners. That said, I'm going to bow out of this issue. This is a general PhET-iO design issue, and I'm way behind on other work. So designers (@arouinfar @kathy-phet) please communicate with @jonathanolson directly. Note that this is needed for the dropper in pH Scale, dev version to be delivered to client by 3/30/2020. |
I'd like to understand more about the desired behavior. Disabling the input listener also wouldn't change the mouse hover cursor for most draggable things. This also has more wide-ranging implications, if we need to change many simple input listeners from raw objects to something that can take a tandem. Additionally, what else in our input listeners should be instrumented? @arouinfar and @kathy-phet, if this needs to be live by 3/30, it would help to discuss it soon! |
@arouinfar - Can you schedule a zoom discuss for this with @jonathanolson? @pixelzoom - We can deliver a dev version without this feature being possible, but it is a bigger issue for other simulations - like Bending light and anything with a timer node. |
@kathy-phet Is this a prerequisite to delivering the final PhET-iO version? |
Only becomes blocking if the client tags it as a blocking issue in their dev review. It wasn't requested by the client for this sim, and it can be added later if needed by a client. However, it did highlight a bigger issue that will occur across simulations, and be more critical in other simulations, so a conversation with @jonathanolson would be good. |
I'm wondering if input listeners is the correct (or only) place to disable interactivity. A Node may have more than 1 input listener. If a client wants to disable interactivity for a Node, they may need to located multiple input listeners (all of which may not necessarily be featured) and set their enabledProperty to It seems like it's more typical to want to disable all interactivity for a Node. Should there be a Node Property to do that? I know that sounds like pickableProperty, but I was thinking of something that's boolean, and doesn't have to deal with restoring pickableProperty to |
There are many trade-offs here, so it would be good to have a better understanding of what the general needs are. |
Possible options:
Basically this boils down to preferring (4), but needing to implement. I'll create a scenery issue for it. Otherwise use (2) if it feels right in a sim-specific case, or if it is needed before (4) is ready. This issue has been discussed and solved, now we just need to implement. Closing. |
Reopening based on discussion in phetsims/scenery-phet#660. In that issue, there is a draggable LaserPointerNode with a button on it. Currently, the draggability is attend by adding the input listener directly to the laser. However, this means when you disable the drag listener (by setting the laser node to be non-interactive or non-pickable) you also disable the button. @pixelzoom indicated one solution would be to make it possible to disable the individual and put listeners. We decided against that in #1041 (comment), but maybe we need to re-evaluate. Another solution investigated in phetsims/scenery-phet#660 (comment) was to add the input listeners to different Nodes, so they could be disabled separately. Is that a workaround or a solution to be embraced? Also, in #1041 (comment) it was argued:
Is there a way to pair the pointer input with the keyboard input so they can be disabled together? Let's start by assigning to @zepumph for discussion, but we may bring this back to dev or phet-io meeting. |
This was the workaround used for the same thing in StopWatchNode, see https://github.com/phetsims/scenery-phet/blob/cc74b53ee659908ce9a7876be3f85c9446232ba6/js/StopwatchNode.js#L213.
If we decided to add enabledProperty to scenery listener Types (likely just PressListener), presumably we would do so with options, so you could pass through your own enabledProperty. If that was the case, then you could pass the same enabledProperty to your collection of listeners to make this a single Property control all input. I really feel like this is a behavior only for PressListener. scenery listeners in general (potential just an object literal) should not be up-converted to something fancy just for this feature. We can see how far something in PressListener gets us, and there is always the option to utilize What about something like this but much better? Index: js/listeners/PressListener.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/js/listeners/PressListener.js b/js/listeners/PressListener.js
--- a/js/listeners/PressListener.js (revision 4b032f5b97d71818393499d9ea41cf8f748cf67c)
+++ b/js/listeners/PressListener.js (date 1612406659218)
@@ -27,6 +27,7 @@
import DerivedProperty from '../../../axon/js/DerivedProperty.js';
import stepTimer from '../../../axon/js/stepTimer.js';
import merge from '../../../phet-core/js/merge.js';
+import EnabledComponent from '../../../sun/js/EnabledComponent.js';
import EventType from '../../../tandem/js/EventType.js';
import PhetioObject from '../../../tandem/js/PhetioObject.js';
import Tandem from '../../../tandem/js/Tandem.js';
@@ -42,7 +43,7 @@
// Factor out to reduce memory footprint, see https://github.com/phetsims/tandem/issues/71
const truePredicate = _.constant( true );
-class PressListener {
+class PressListener extends EnabledComponent {
/**
* @param {Object} [options] - See the constructor body (below) for documented options.
*/
@@ -138,6 +139,8 @@
assert && assert( typeof options.a11yLooksPressedInterval === 'number',
'a11yLooksPressedInterval should be a number' );
+ super( options );
+
// @private {number} - Unique global ID for this listener
this._id = globalID++;
@@ -310,6 +313,8 @@
// update isHighlightedProperty (not a DerivedProperty because we need to hook to passed-in properties)
this.isHoveringProperty.link( this._isHighlightedListener );
this.isPressedProperty.link( this._isHighlightedListener );
+
+ this.enabledProperty.lazyLink( enabled => !enabled && this.interrupt() );
}
/**
@@ -388,6 +393,10 @@
sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( `PressListener#${this._id} press` );
+ if ( !this.enabledProperty.value ) {
+ return;
+ }
+
if ( !this.canPress( event ) ) {
sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( `PressListener#${this._id} could not press` );
return false;
@@ -538,6 +547,11 @@
* @private
*/
invalidateOver() {
+
+ if ( !this.enabledProperty.value ) {
+ return;
+ }
+
let pointerAttachedToOther = false;
if ( this._listeningToPointer ) {
@@ -568,6 +582,9 @@
* @private
*/
invalidateHovering() {
+ if ( !this.enabledProperty.value ) {
+ return;
+ }
for ( let i = 0; i < this.overPointers.length; i++ ) {
const pointer = this.overPointers[ i ];
if ( !pointer.isDown || pointer === this.pointer ) {
@@ -694,6 +711,10 @@
sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( `PressListener#${this._id} enter` );
sceneryLog && sceneryLog.InputListener && sceneryLog.push();
+ if ( !this.enabledProperty.value ) {
+ return;
+ }
+
this.overPointers.push( event.pointer );
sceneryLog && sceneryLog.InputListener && sceneryLog.pop();
@@ -727,6 +748,10 @@
sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( `PressListener#${this._id} exit` );
sceneryLog && sceneryLog.InputListener && sceneryLog.push();
+ if ( !this.enabledProperty.value ) {
+ return;
+ }
+
// NOTE: We don't require the pointer to be included here, since we may have added the listener after the 'enter'
// was fired. See https://github.com/phetsims/area-model-common/issues/159 for more details.
if ( this.overPointers.includes( event.pointer ) ) {
@@ -748,6 +773,10 @@
sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( `PressListener#${this._id} pointer up` );
sceneryLog && sceneryLog.InputListener && sceneryLog.push();
+ if ( !this.enabledProperty.value ) {
+ return;
+ }
+
// Since our callback can get queued up and THEN interrupted before this happens, we'll check to make sure we are
// still pressed by the time we get here. If not pressed, then there is nothing to do.
// See https://github.com/phetsims/capacitor-lab-basics/issues/251
@@ -771,6 +800,9 @@
pointerCancel( event ) {
sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( `PressListener#${this._id} pointer cancel` );
sceneryLog && sceneryLog.InputListener && sceneryLog.push();
+ if ( !this.enabledProperty.value ) {
+ return;
+ }
// Since our callback can get queued up and THEN interrupted before this happens, we'll check to make sure we are
// still pressed by the time we get here. If not pressed, then there is nothing to do.
@@ -795,6 +827,9 @@
pointerMove( event ) {
sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( `PressListener#${this._id} pointer move` );
sceneryLog && sceneryLog.InputListener && sceneryLog.push();
+ if ( !this.enabledProperty.value ) {
+ return;
+ }
// Since our callback can get queued up and THEN interrupted before this happens, we'll check to make sure we are
// still pressed by the time we get here. If not pressed, then there is nothing to do.
@@ -823,6 +858,9 @@
sceneryLog && sceneryLog.InputListener && sceneryLog.InputListener( `PressListener#${this._id} pointer interrupt` );
sceneryLog && sceneryLog.InputListener && sceneryLog.push();
+ if ( !this.enabledProperty.value ) {
+ return;
+ }
this.interrupt();
sceneryLog && sceneryLog.InputListener && sceneryLog.pop();
@@ -844,6 +882,10 @@
* @param {function} [callback] optionally called immediately after press, but only on successful click
*/
click( event, callback ) {
+ if ( !this.enabledProperty.value ) {
+ return;
+ }
+
if ( this.canClick() ) {
this.interrupted = false; // clears the flag (don't set to false before here)
@@ -887,6 +929,9 @@
* @pdom
*/
focus( event ) {
+ if ( !this.enabledProperty.value ) {
+ return;
+ }
// Get the Display related to this accessible event.
const accessibleDisplays = event.trail.rootNode().getRootedDisplays().filter( display => display.isAccessible() );
@@ -908,6 +953,10 @@
* @pdom
*/
blur() {
+ if ( !this.enabledProperty.value ) {
+ return;
+ }
+
if ( this.display ) {
if ( this.display.focusHighlightsVisibleProperty.hasListener( this.boundInvalidateOverListener ) ) {
this.display.focusHighlightsVisibleProperty.unlink( this.boundInvalidateOverListener );
@@ -958,6 +1007,8 @@
this.display = null;
}
+ super.dispose();
+
sceneryLog && sceneryLog.InputListener && sceneryLog.pop();
}
}
|
@zepumph said:
I don't think this is exclusive to the PressListener hierachy. This seems important for KeyboardDragListener, and maybe some of the other next-gen input listeners in scenery/listeners/. If instead you meant "I don't think this is necessary for old-stype input listeners and literal |
@kathy-phet asked me to take the lead on this, as it pertains to Bending Light. @pixelzoom mentioned we may add |
2/4/21 phet-io meeting: Expecting clients to set something like Using Rather than exposing internal listeners and Nodes, I suggested adding Properties for enabling/disabling types of interactions. For example a draggable laser might have |
I proposed a design and implementation strategy for this problem as it appears in the context of Bending Light, and it is pending review by @arouinfar and @pixelzoom in phetsims/bending-light#397 (comment), putting this more general issue on hold until we have discussed that specific case. |
We agreed the implementation in phetsims/bending-light#397 seems like a suitable pattern for simulations (or common code) to use, and @zepumph will have an opportunity to try this pattern in Projectile Motion for some upcoming features. Perhaps after Projectile Motion, we can reflect on this process and determine if additional steps, such as documentation in the instrumentation guide, are warranted. @pixelzoom does that sound reasonable? |
I have noted this pattern, and will pick this up over in PM as needed. |
Over in phetsims/ph-scale#118 (comment) @kathy-phet noted about the dropper in ph-scale:
I said:
@arouinfar said:
The text was updated successfully, but these errors were encountered: