Skip to content

Commit

Permalink
convert from keyboardDragListener to accessibleSlider, support "snap-…
Browse files Browse the repository at this point in the history
…to" keyboard nav, #47
  • Loading branch information
zepumph committed May 18, 2020
1 parent c6f865c commit 05189d7
Showing 1 changed file with 76 additions and 48 deletions.
124 changes: 76 additions & 48 deletions js/free-objects/view/RatioHalf.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,18 @@

import BooleanProperty from '../../../../axon/js/BooleanProperty.js';
import DerivedProperty from '../../../../axon/js/DerivedProperty.js';
import Property from '../../../../axon/js/Property.js';
import Dimension2 from '../../../../dot/js/Dimension2.js';
import Vector2 from '../../../../dot/js/Vector2.js';
import merge from '../../../../phet-core/js/merge.js';
import ModelViewTransform2 from '../../../../phetcommon/js/view/ModelViewTransform2.js';
import ArrowNode from '../../../../scenery-phet/js/ArrowNode.js';
import PlusNode from '../../../../scenery-phet/js/PlusNode.js';
import DragListener from '../../../../scenery/js/listeners/DragListener.js';
import KeyboardDragListener from '../../../../scenery/js/listeners/KeyboardDragListener.js';
import Circle from '../../../../scenery/js/nodes/Circle.js';
import Image from '../../../../scenery/js/nodes/Image.js';
import Rectangle from '../../../../scenery/js/nodes/Rectangle.js';
import AccessibleSlider from '../../../../sun/js/accessibility/AccessibleSlider.js';
import SoundClip from '../../../../tambo/js/sound-generators/SoundClip.js';
import soundManager from '../../../../tambo/js/soundManager.js';
import Tandem from '../../../../tandem/js/Tandem.js';
Expand Down Expand Up @@ -91,34 +92,11 @@ class RatioHalf extends Rectangle {
this.alertManager = new FreeObjectAlertManager( valueProperty, gridViewProperty, ratioDescriber, gridDescriber, options.isRight );

// The draggable element inside the Node framed with thick rectangles on the top and bottom.
const pointer = new Node( {

// pdom
tagName: 'div',
role: 'application',
focusable: true
const pointer = new Pointer( valueProperty, valueRange, {
startDrag: () => { firstInteractionProperty.value = false; }
} );
this.addChild( pointer );

const handNode = new Image( filledInHandImage );

// Flip the hand if it isn't a right hand.
handNode.setScaleMagnitude( ( options.isRight ? 1 : -1 ) * .4, .4 );
handNode.right = handNode.width / 2;
handNode.bottom = handNode.height / 2;

const circle = new Circle( 20, {
fill: 'black'
} );
circle.center = Vector2.ZERO;

const cross = new PlusNode( {
size: new Dimension2( 40, 8 )
} );
const crossBackground = Rectangle.bounds( cross.bounds );
const crossNode = new Node( { children: [ cross, crossBackground ] } );
crossNode.center = Vector2.ZERO;

// Sound for the wave slider clicks
const addSoundOptions = { categoryName: 'user-interface' };
const soundClipOptions = {
Expand Down Expand Up @@ -183,14 +161,6 @@ class RatioHalf extends Rectangle {
}
} );
pointer.addInputListener( dragListener );

// transform and dragBounds set in layout code below
const keyboardDragListener = new KeyboardDragListener( {
positionProperty: positionProperty,
start: () => { firstInteractionProperty.value = false; },
end: () => this.alertManager.dragEndListener( valueProperty.get() )
} );
pointer.addInputListener( keyboardDragListener );
pointer.addInputListener( {
focus: () => {
commonGrabSoundClip.play();
Expand Down Expand Up @@ -238,22 +208,10 @@ class RatioHalf extends Rectangle {
const dragBounds = positionProperty.validBounds.erodedX( modelHalfPointerPointer.x );

dragListener.dragBounds = dragBounds;
keyboardDragListener.dragBounds = dragBounds;
};

designingProperties.markerDisplayProperty.link( displayType => {
if ( displayType === CursorDisplay.CIRCLE ) {
pointer.children = [ circle ];
}
else if ( displayType === CursorDisplay.CROSS ) {
pointer.children = [ crossNode ];
}
else if ( displayType === CursorDisplay.HAND ) {
pointer.children = [ handNode ];
}
else {
assert && assert( false, `unsupported displayType: ${displayType}` );
}
pointer.updatePointerView( displayType );
recomputeDragBounds();
} );

Expand Down Expand Up @@ -288,7 +246,6 @@ class RatioHalf extends Rectangle {

recomputeDragBounds();
dragListener.transform = modelViewTransform;
keyboardDragListener.transform = modelViewTransform;
};
}

Expand All @@ -311,5 +268,76 @@ class RatioHalf extends Rectangle {
// @public - the height of the top and bottom rectangles
RatioHalf.FRAMING_RECTANGLE_HEIGHT = FRAMING_RECTANGLE_HEIGHT;

class Pointer extends Node {

/**
*
* @param {Property.<number>} valueProperty
* @param {Range} valueRange
* @param {Object} [options]
*/
constructor( valueProperty, valueRange, options ) {

options = merge( {}, options );
super();

// Always the same range, always enabled
this.initializeAccessibleSlider( valueProperty, new Property( valueRange ), new BooleanProperty( true ), options );

// @private
this.handNode = new Image( filledInHandImage );

// Flip the hand if it isn't a right hand.
this.handNode.setScaleMagnitude( ( options.isRight ? 1 : -1 ) * .4, .4 );
this.handNode.right = this.handNode.width / 2;
this.handNode.bottom = this.handNode.height / 2;

// @private
this.circleNode = new Circle( 20, {
fill: 'black'
} );
this.circleNode.center = Vector2.ZERO;

const cross = new PlusNode( {
size: new Dimension2( 40, 8 )
} );
const crossBackground = Rectangle.bounds( cross.bounds );

// @private
this.crossNode = new Node( { children: [ cross, crossBackground ] } );
this.crossNode.center = Vector2.ZERO;

designingProperties.gridBaseUnitProperty.link( baseUnit => {
const downDelta = 1 / baseUnit;
this.setKeyboardStep( downDelta );
this.setShiftKeyboardStep( downDelta / 4 );
this.setPageKeyboardStep( 1 / 5 );
} );

this.mutate( options );
}

/**
* @public
* @param {CursorDisplay} cursorDisplay
*/
updatePointerView( cursorDisplay ) {
if ( cursorDisplay === CursorDisplay.CIRCLE ) {
this.children = [ this.circleNode ];
}
else if ( cursorDisplay === CursorDisplay.CROSS ) {
this.children = [ this.crossNode ];
}
else if ( cursorDisplay === CursorDisplay.HAND ) {
this.children = [ this.handNode ];
}
else {
assert && assert( false, `unsupported cursorDisplay: ${cursorDisplay}` );
}
}
}

AccessibleSlider.mixInto( Pointer );

ratioAndProportion.register( 'RatioHalf', RatioHalf );
export default RatioHalf;

0 comments on commit 05189d7

Please sign in to comment.