Skip to content

Commit

Permalink
pdom draft complete, TODO: proper string utilization and ensure enabl…
Browse files Browse the repository at this point in the history
…ing/disabling of appropriate elements, see #109
  • Loading branch information
mbarlow12 committed Oct 26, 2018
1 parent c4a2aae commit 404738b
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 44 deletions.
11 changes: 10 additions & 1 deletion js/gravity-force-lab/GravityForceLabA11yStrings.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,16 @@ define( require => {
value: 'Currently, force on m1 by m2 is of equal magnitude and pointing directly opposite to the force on m2 by m1.'
},
massValuesAndComparisonSummaryPattern: {
value: 'Mass of m1 is {{m1Mass}} kilograms, {{comparitiveValue}} m2 at {{m2Mass}} kilograms.'
value: 'Mass of {{mass1Label}} is {{m1Mass}} kilograms, {{comparitiveValue}} {{mass2Label}} at {{m2Mass}} kilograms.'
},

// Object/sphere descriptions and labels

mass1BlueSphere: {
value: 'm1, Blue Sphere'
},
mass2RedSphere: {
value: 'm2, Red Sphere'
},

////////////////////////
Expand Down
5 changes: 2 additions & 3 deletions js/gravity-force-lab/view/GravityForceLabScreenSummaryNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ define( require => {
// modules
const gravityForceLab = require( 'GRAVITY_FORCE_LAB/gravityForceLab' );
const GravityForceLabA11yStrings = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/GravityForceLabA11yStrings' );
const GravityForceLabStringManager = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/GravityForceLabStringManager' );
const Node = require( 'SCENERY/nodes/Node' );
const Property = require( 'AXON/Property' );

Expand All @@ -22,14 +21,14 @@ define( require => {

class GravityForceLabScreenSummaryNode extends Node {

constructor( model ) {
constructor( model, stringManager ) {
super( {
tagName: 'div',
descriptionTagName: 'p',
descriptionContent: screenSummaryDescriptionString
} );

this.stringManager = new GravityForceLabStringManager( model );
this.stringManager = stringManager;

this.simStateNode = new Node( {
tagName: 'ul',
Expand Down
108 changes: 75 additions & 33 deletions js/gravity-force-lab/view/GravityForceLabScreenView.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,25 @@ define( function( require ) {
// modules
// var ParameterControlPanel = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/ParameterControlPanel' );
var Bounds2 = require( 'DOT/Bounds2' );
var ControlAreaNode = require( 'SCENERY_PHET/accessibility/nodes/ControlAreaNode' );
var gravityForceLab = require( 'GRAVITY_FORCE_LAB/gravityForceLab' );
var GravityForceLabConstants = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/GravityForceLabConstants' );
// var GravityForceLabA11yStrings = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/GravityForceLabA11yStrings' );
var GravityForceLabScreenSummaryNode = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/GravityForceLabScreenSummaryNode' );
var GravityForceLabStringManager = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/GravityForceLabStringManager' );
var inherit = require( 'PHET_CORE/inherit' );
var ISLCA11yStrings = require( 'INVERSE_SQUARE_LAW_COMMON/ISLCA11yStrings' );
var ISLCCheckboxItem = require( 'INVERSE_SQUARE_LAW_COMMON/view/ISLCCheckboxItem' );
var ISLCCheckboxPanel = require( 'INVERSE_SQUARE_LAW_COMMON/view/ISLCCheckboxPanel' );
var ISLCGridNode = require( 'INVERSE_SQUARE_LAW_COMMON/view/ISLCGridNode' );
var ISLCObjectEnum = require( 'INVERSE_SQUARE_LAW_COMMON/view/ISLCObjectEnum' );
var ISLCRulerNode = require( 'INVERSE_SQUARE_LAW_COMMON/view/ISLCRulerNode' );
var ISLCQueryParameters = require( 'INVERSE_SQUARE_LAW_COMMON/ISLCQueryParameters' );
var MassControl = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/MassControl' );
var MassNode = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/MassNode' );
var MassPDOMNode = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/MassPDOMNode' );
var ModelViewTransform2 = require( 'PHETCOMMON/view/ModelViewTransform2' );
// var Node = require( 'SCENERY/nodes/Node' );
var Node = require( 'SCENERY/nodes/Node' );
var PlayAreaNode = require( 'SCENERY_PHET/accessibility/nodes/PlayAreaNode' );
var ResetAllButton = require( 'SCENERY_PHET/buttons/ResetAllButton' );
var ScreenView = require( 'JOIST/ScreenView' );
var Vector2 = require( 'DOT/Vector2' );
Expand All @@ -41,19 +46,30 @@ define( function( require ) {
var forceValuesString = require( 'string!INVERSE_SQUARE_LAW_COMMON/forceValues' );
var unitsMetersString = require( 'string!GRAVITY_FORCE_LAB/units.meters' );

// a11y Strings
const spherePositionsString = ISLCA11yStrings.spherePositions.value;
const spherePositionHelpTextString = ISLCA11yStrings.spherePositionHelpText.value;

// constants
var CONTROL_SCALE = 0.72;
var SHOW_GRID = ISLCQueryParameters.showGrid;
var OBJECT_ONE = ISLCObjectEnum.OBJECT_ONE;
var OBJECT_TWO = ISLCObjectEnum.OBJECT_TWO;

function GravityForceLabScreenView( model, tandem ) {
ScreenView.call( this, {
layoutBounds: new Bounds2( 0, 0, 768, 464 ),
addScreenSummaryNode: true,
tandem: tandem
} );
var stringManager = new GravityForceLabStringManager( model, mass1AbbreviatedString, mass2AbbreviatedString );
var summaryNode = new GravityForceLabScreenSummaryNode( model, stringManager );
var playAreaNode = new PlayAreaNode();
var controlAreaNode = new ControlAreaNode();

const summaryNode = new GravityForceLabScreenSummaryNode( model );
this.screenSummaryNode.addChild( summaryNode );
this.addChild( playAreaNode );
this.addChild( controlAreaNode );

// Create the model-view transform. The primary units used in the model are meters, so significant zoom is used.
// The multipliers for the 2nd parameter can be used to adjust where the point (0, 0) in the model, which is
Expand Down Expand Up @@ -93,13 +109,30 @@ define( function( require ) {
}
);

this.addChild( massNode1 );
this.addChild( massNode2 );
playAreaNode.addChild( new MassPDOMNode( model, OBJECT_ONE, stringManager, {
thisObjectLabel: mass1AbbreviatedString,
otherObjectLabel: mass2AbbreviatedString
} ) );
playAreaNode.addChild( new MassPDOMNode( model, OBJECT_TWO, stringManager, {
thisObjectLabel: mass2AbbreviatedString,
otherObjectLabel: mass1AbbreviatedString
} ) );

var massPositionsNode = new Node( {
tagName: 'ul',
labelTagName: 'h3',
labelContent: spherePositionsString,
descriptionContent: spherePositionHelpTextString
} );

playAreaNode.addChild( massPositionsNode );
massPositionsNode.addChild( massNode1 );
massPositionsNode.addChild( massNode2 );

// the arrows and their labels should be above both masses (and their markers) but below
// the ruler and control panels
this.addChild( massNode1.arrowNode );
this.addChild( massNode2.arrowNode );
playAreaNode.addChild( massNode1.arrowNode );
playAreaNode.addChild( massNode2.arrowNode );

// @private - added to object for animation stepping
var gravityForceLabRuler = new ISLCRulerNode(
Expand All @@ -113,14 +146,35 @@ define( function( require ) {
snapToNearest: GravityForceLabConstants.LOCATION_SNAP_VALUE
}
);
this.addChild( gravityForceLabRuler );
playAreaNode.addChild( gravityForceLabRuler );

var resetAllButton = new ResetAllButton( {
listener: function() { model.reset(); },
scale: 0.81,
tandem: tandem.createTandem( 'resetAllButton' )
// TODO: implement proper string usage
var massControlsNode = new Node( {
labelTagName: 'h3',
labelContent: 'Mass Controls',
tagName: 'ul'
} );
this.addChild( resetAllButton );
playAreaNode.addChild( massControlsNode );

var massControl1 = new MassControl(
mass1String,
model.object1.valueProperty,
GravityForceLabConstants.MASS_RANGE,
GravityForceLabConstants.MASS_BLUE_COLOR,
tandem.createTandem( 'massControl1' )
);
massControl1.scale( CONTROL_SCALE );
massControlsNode.addChild( massControl1 );

var massControl2 = new MassControl(
mass2String,
model.object2.valueProperty,
GravityForceLabConstants.MASS_RANGE,
GravityForceLabConstants.MASS_RED_COLOR,
tandem.createTandem( 'massControl2' )
);
massControl2.scale( CONTROL_SCALE );
massControlsNode.addChild( massControl2 );

var TEXT_SIZE = 15;
var checkboxItems = [
Expand Down Expand Up @@ -150,29 +204,17 @@ define( function( require ) {
minWidth: 170,
align: 'left'
} );
this.addChild( parameterControlPanel );

var massControl1 = new MassControl(
mass1String,
model.object1.valueProperty,
GravityForceLabConstants.MASS_RANGE,
GravityForceLabConstants.MASS_BLUE_COLOR,
tandem.createTandem( 'massControl1' )
);
massControl1.scale( CONTROL_SCALE );
this.addChild( massControl1 );
controlAreaNode.addChild( parameterControlPanel );

var massControl2 = new MassControl(
mass2String,
model.object2.valueProperty,
GravityForceLabConstants.MASS_RANGE,
GravityForceLabConstants.MASS_RED_COLOR,
tandem.createTandem( 'massControl2' )
);
massControl2.scale( CONTROL_SCALE );
this.addChild( massControl2 );
var resetAllButton = new ResetAllButton( {
listener: function() { model.reset(); },
scale: 0.81,
tandem: tandem.createTandem( 'resetAllButton' )
} );
controlAreaNode.addChild( resetAllButton );

// positioning the nodes
// TODO: Position based on layout (consider using HBox like GFL:B)
parameterControlPanel.right = this.layoutBounds.width - 15;
parameterControlPanel.top = gravityForceLabRuler.bottom + 15;
massControl2.right = parameterControlPanel.left - 45;
Expand Down
58 changes: 53 additions & 5 deletions js/gravity-force-lab/view/GravityForceLabStringManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ define( require => {

// strings
const micronewtonsString = GravityForceLabA11yStrings.micronewtons.value;
const mass1AbbreviatedString = require( 'string!GRAVITY_FORCE_LAB/mass1Abbreviated' );
const mass2AbbreviatedString = require( 'string!GRAVITY_FORCE_LAB/mass2Abbreviated' );
// const mass1AbbreviatedString = require( 'string!GRAVITY_FORCE_LAB/mass1Abbreviated' );
// const mass2AbbreviatedString = require( 'string!GRAVITY_FORCE_LAB/mass2Abbreviated' );

const massValuesAndComparisonSummaryPatternString = GravityForceLabA11yStrings.massValuesAndComparisonSummaryPattern.value;
const sizeAndPositionPatternString = '{{thisObject}} is {{size}} at {{massValue}} kg and at {{positionMark}} meter mark';

const muchMuchSmallerThanString = GravityForceLabA11yStrings.muchMuchSmallerThan.value;
const muchSmallerThanString = GravityForceLabA11yStrings.muchSmallerThan.value;
Expand All @@ -46,11 +47,14 @@ define( require => {
const forceToPullIndex = new LinearFunction( min, max, 6, 0, true );

class GravityForceLabStringManager extends ISLCStringManager {
constructor( model ) {
super( model, mass1AbbreviatedString, mass2AbbreviatedString, {
constructor( model, object1Label, object2Label, options ) {

options = options ? options : _.extend( {
valueUnits: micronewtonsString,
valueUnitConversion: MICRO_CONVERSION_FACTOR
} );
}, options );

super( model, object1Label, object2Label, options );

// @private
this._object1ToObject2Ratio = 0;
Expand All @@ -72,18 +76,62 @@ define( require => {
getMassValuesSummaryText() {
const relativeSizeIndex = Util.roundSymmetric( this.getRelativeSizeIndex( this._object1ToObject2Ratio ) );
const fillObject = {
mass1Label: this.object1Label,
mass2Label: this.object2Label,
m1Mass: this.object1.valueProperty.get(),
m2Mass: this.object2.valueProperty.get(),
comparitiveValue: RELATIVE_SIZE_STRINGS[ relativeSizeIndex ]
};
return StringUtils.fillIn( massValuesAndComparisonSummaryPatternString, fillObject );
}

// Mass/sphere strings
getSizeAndPositionItemText( massLabel ) {
const modelObject = massLabel === this.object1Label ? this.object1 : this.object2;
const thisObject = massLabel;
const massValue = modelObject.valueProperty.get();
const size = this.getSizeOfMass( massValue );
const positionMark = Util.toFixedNumber( modelObject.positionProperty.get() + 5, 1 );
const pattern = sizeAndPositionPatternString;
return StringUtils.fillIn( pattern, { thisObject, size, massValue, positionMark } );
}

getSizeOfMass( massValue ) {
const massIndex = this.getMassSizeIndex( massValue );
return this.getSizeFromIndex( massIndex );
}

getRelativeSizeIndex( ratio ) {
const exp = Math.log10( ratio );
return Util.roundSymmetric( exponentToIndex( exp ) );
}

getMassSizeIndex( mass ) {
assert && assert( ( typeof mass ) === 'number' );
if ( mass < 26 ) {
return 0;
}
if ( mass < 101 ) {
return 1;
}
if ( mass < 401 ) {
return 2;
}
if ( mass < 601 ) {
return 3;
}
if ( mass < 801 ) {
return 4;
}
if ( mass < 901 ) {
return 5;
}
if ( mass <= 1000 ) {
return 6;
}
throw Error( 'Invalid mass value.');
}

///////////////
// Overrides //
///////////////
Expand Down
5 changes: 4 additions & 1 deletion js/gravity-force-lab/view/MassControl.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ define( function( require ) {
thumbFillHighlighted: thumbColor.colorUtilsBrighter( 0.35 ),

// a11y
keyboardStep: 50
// TODO: review proper string implementation
keyboardStep: 50,
accessibleName: titleString,
accessibleValuePattern: '{{value}} kilograms'
},

tickLabelOptions: {
Expand Down
9 changes: 8 additions & 1 deletion js/gravity-force-lab/view/MassNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,14 @@ define( function( require ) {
// see https://github.com/phetsims/inverse-square-law-common/issues/21
maxArrowWidth: 300,

tandem: Tandem.required
tandem: Tandem.required,

// a11y
// TODO: refactor into proper string usage
createAriaValueText: function( formattedValue, previousValue ) {
formattedValue += 5;
return `${formattedValue} meter mark`;
}
}, options );

// @private
Expand Down
37 changes: 37 additions & 0 deletions js/gravity-force-lab/view/MassPDOMNode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2013-2018, University of Colorado Boulder

define( require => {
'use strict';

// modules
const gravityForceLab = require( 'GRAVITY_FORCE_LAB/gravityForceLab' );
const GravityForceLabA11yStrings = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/GravityForceLabA11yStrings' );
const ISLCObjectEnum = require( 'INVERSE_SQUARE_LAW_COMMON/view/ISLCObjectEnum' );
const ISLCObjectPDOMNode = require( 'INVERSE_SQUARE_LAW_COMMON/view/ISLCObjectPDOMNode' );
const Node = require( 'SCENERY/nodes/Node' );

// strings
const mass1BlueSphereString = GravityForceLabA11yStrings.mass1BlueSphere.value;
const mass2RedSphereString = GravityForceLabA11yStrings.mass2RedSphere.value;

class MassPDOMNode extends ISLCObjectPDOMNode {

constructor( model, objectEnum, stringManager, options ) {

const labelContent = objectEnum === ISLCObjectEnum.OBJECT_ONE ? mass1BlueSphereString : mass2RedSphereString;
options.a11yOptions = { labelContent };

super( model, objectEnum, stringManager, options );

this.massAndPositionNode = new Node( { tagName: 'li' } );
this.addChild( this.massAndPositionNode );

this.linkToForceProperty( force => {
const newContent = stringManager.getSizeAndPositionItemText( this.thisObjectLabel );
this.massAndPositionNode.innerContent = newContent;
} );
}
}

return gravityForceLab.register( 'MassPDOMNode', MassPDOMNode );
} );

0 comments on commit 404738b

Please sign in to comment.