From b730aa26200d169c4c9d544b50cd785d7f7bc33f Mon Sep 17 00:00:00 2001 From: Michael Barlow Date: Tue, 11 Dec 2018 20:27:45 -0700 Subject: [PATCH] move createAriaValueText implementation to screenView, mirror implementation from GFL see commits in phetsims/gravity-force-lab#124 --- .../view/GravityForceLabBasicsMassNode.js | 14 ++-- .../view/GravityForceLabBasicsScreenView.js | 79 ++++++++++++++++++- 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/js/gravity-force-lab-basics/view/GravityForceLabBasicsMassNode.js b/js/gravity-force-lab-basics/view/GravityForceLabBasicsMassNode.js index 45e4c55..3d3356f 100644 --- a/js/gravity-force-lab-basics/view/GravityForceLabBasicsMassNode.js +++ b/js/gravity-force-lab-basics/view/GravityForceLabBasicsMassNode.js @@ -46,12 +46,7 @@ define( function( require ) { y: MASS_NODE_Y_POSITION, snapToNearest: model.snapObjectsToNearest, // in meters, charges will snap to the nearest 0.1 meters in model coordinates - tandem: Tandem.required, - - // a11y - createAriaValueText: function( formattedValue, previousValue ) { - return stringManager.getSpherePositionAriaValueText( formattedValue, self ); - } + tandem: Tandem.required }, options ); // @private @@ -84,8 +79,11 @@ define( function( require ) { }, resetAriaValueText: function() { - var position = this.objectModel.positionProperty.get(); - this.ariaValueText = this.stringManager.getSpherePositionAndRegionText( position, this.enum ); + if ( this.objectModel.isAtEdgeOfRange() ) { + this.ariaValueText = this.stringManager.getLastStopDistanceFromOtherObjectText( this.enum ); + return; + } + this.ariaValueText = this.stringManager.getPositionAndDistanceFromOtherObjectText( this.enum ); // position = Util.toFixedNumber( ( position + 4800 ) / 1e3, 1 ); // this.ariaValueText = GFLBStringManager.getPositionMeterMarkText( `${position} kilometer reset` ); } diff --git a/js/gravity-force-lab-basics/view/GravityForceLabBasicsScreenView.js b/js/gravity-force-lab-basics/view/GravityForceLabBasicsScreenView.js index 3d02a7d..727b53f 100644 --- a/js/gravity-force-lab-basics/view/GravityForceLabBasicsScreenView.js +++ b/js/gravity-force-lab-basics/view/GravityForceLabBasicsScreenView.js @@ -35,9 +35,11 @@ define( function( require ) { var MassPDOMNode = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/MassPDOMNode' ); var ModelViewTransform2 = require( 'PHETCOMMON/view/ModelViewTransform2' ); var Node = require( 'SCENERY/nodes/Node' ); + var Property = require( 'AXON/Property' ); var PlayAreaNode = require( 'SCENERY_PHET/accessibility/nodes/PlayAreaNode' ); var ResetAllButton = require( 'SCENERY_PHET/buttons/ResetAllButton' ); var ScreenView = require( 'JOIST/ScreenView' ); + var Util = require( 'DOT/Util' ); var Vector2 = require( 'DOT/Vector2' ); // constants @@ -106,6 +108,36 @@ define( function( require ) { .05 ); + // position state variables + var lastMoveCloser = false; + var movedCloser = false; + var distanceBetween = Math.abs( model.object2.positionProperty.get() - model.object1.positionProperty.get() ); + + function ariaValueTextCreator( objectEnum ) { + return function( formattedValue, oldValue ) { + var thisObjectEnum = objectEnum; + var thisObject = thisObjectEnum === OBJECT_ONE ? model.object1 : model.object2; + var newDistanceBetween = Math.abs( model.object1.positionProperty.get() - model.object2.positionProperty.get() ); + newDistanceBetween = Util.toFixedNumber( newDistanceBetween, 1 ); + var newAriaValueText = stringManager.getDistanceFromOtherObjectText( thisObjectEnum, newDistanceBetween ); + + movedCloser = newDistanceBetween < distanceBetween; + + if ( lastMoveCloser !== movedCloser ) { + newAriaValueText = stringManager.getProgressPositionAndDistanceFromOtherObjectText( thisObjectEnum, movedCloser, newDistanceBetween ); + } + + if ( thisObject.isAtEdgeOfRange() ) { + // last stop + newAriaValueText = stringManager.getLastStopDistanceFromOtherObjectText( thisObjectEnum, newDistanceBetween ); + } + + lastMoveCloser = movedCloser; + distanceBetween = newDistanceBetween; + return newAriaValueText; + }; + } + // add the mass nodes to the view var mass1Node = new GravityForceLabBasicsMassNode( model, model.object1, this.layoutBounds, stringManager, modelViewTransform, { label: mass1LabelString, @@ -113,7 +145,8 @@ define( function( require ) { defaultDirection: 'left', arrowColor: '#66F', forceArrowHeight: 125, - tandem: tandem.createTandem( 'mass1Node' ) + tandem: tandem.createTandem( 'mass1Node' ), + createAriaValueText: ariaValueTextCreator( OBJECT_ONE ) } ); var mass2Node = new GravityForceLabBasicsMassNode( model, model.object2, this.layoutBounds, stringManager, modelViewTransform, { @@ -122,7 +155,8 @@ define( function( require ) { defaultDirection: 'right', arrowColor: '#F66', forceArrowHeight: 175, - tandem: tandem.createTandem( 'mass2Node' ) + tandem: tandem.createTandem( 'mass2Node' ), + createAriaValueText: ariaValueTextCreator( OBJECT_TWO ) } ); playAreaNode.addChild( new MassPDOMNode( model, OBJECT_ONE, stringManager, { @@ -243,6 +277,47 @@ define( function( require ) { // a11y - specify the order of focus for things in the ScreenView // this.accessibleOrder = [ mass1Node, mass2Node, massControlBox, parameterControlPanel, resetAllButton ]; + Property.multilink( + [ model.object1.positionProperty, model.object2.positionProperty ], + function( x1, x2 ) { + var focusedMassNode; + var otherMassNode; + var distance = Util.toFixedNumber( Math.abs( x1 - x2 ), 1 ); + + if ( mass1Node.isFocused() ) { + focusedMassNode = mass1Node; + otherMassNode = mass2Node; + } + else if ( mass2Node.isFocused() ) { + focusedMassNode = mass2Node; + otherMassNode = mass1Node; + } + else { + // this case is possible if the radius of a mass pushes the other mass + mass1Node.ariaValueText = stringManager.getPositionAndDistanceFromOtherObjectText( OBJECT_ONE, distance ); + mass2Node.ariaValueText = stringManager.getPositionAndDistanceFromOtherObjectText( OBJECT_TWO, distance ); + return; + } + + var newAriaValueText = stringManager.getPositionAndDistanceFromOtherObjectText( otherMassNode.enum, distance ); + + if ( focusedMassNode.objectModel.isAtEdgeOfRange() ) { + newAriaValueText = stringManager.getLastStopDistanceFromOtherObjectText( otherMassNode.enum, distance ); + } + otherMassNode.ariaValueText = newAriaValueText; + } + ); + + function focusListenerCreator( objectNode ) { + return function( event ) { + lastMoveCloser = null; + objectNode.resetAriaValueText(); + }; + } + + mass1Node.addInputListener( { focus: focusListenerCreator( mass1Node ) } ); + mass2Node.addInputListener( { focus: focusListenerCreator( mass2Node ) } ); + //------------------------------------------------ // debugging //------------------------------------------------