From 670dd9a24dbda6cc9c8f35bf4234e7e2957422d2 Mon Sep 17 00:00:00 2001 From: Marla Schulz Date: Thu, 6 Feb 2025 15:46:11 -0800 Subject: [PATCH] Rename NumberSentenceAccordionBox to NumberPhraseAccordionBox and update accessibleName/HelpText, see: https://github.com/phetsims/number-pairs/issues/78 --- js/NumberPairsStrings.ts | 29 ++++--- js/common/model/RepresentationType.ts | 2 +- js/common/view/BeadsOnWireNode.ts | 3 +- js/common/view/CountingAreaNode.ts | 2 + js/common/view/EquationAccordionBox.ts | 4 +- js/common/view/NumberBondAccordionBox.ts | 8 +- js/common/view/NumberPairsScreenView.ts | 32 +++++--- ...dionBox.ts => NumberPhraseAccordionBox.ts} | 28 +++---- .../view/RepresentationRadioButtonGroup.ts | 1 + .../view/SceneSelectionRadioButtonGroup.ts | 7 +- js/common/view/ShowHideAddendButton.ts | 76 +++++++++---------- js/intro/view/IntroScreenView.ts | 10 +-- js/intro/view/SplitCountingAreaNode.ts | 3 + js/sum/view/SumScreenView.ts | 11 +-- js/ten/view/TenScreenView.ts | 10 +-- js/twenty/view/TwentyScreenView.ts | 10 +-- number-pairs-strings_en.json | 59 +++++++++----- 17 files changed, 171 insertions(+), 124 deletions(-) rename js/common/view/{NumberSentenceAccordionBox.ts => NumberPhraseAccordionBox.ts} (91%) diff --git a/js/NumberPairsStrings.ts b/js/NumberPairsStrings.ts index 7b303fb..4812b92 100644 --- a/js/NumberPairsStrings.ts +++ b/js/NumberPairsStrings.ts @@ -22,12 +22,14 @@ type StringsType = { 'sumStringProperty': LocalizedStringProperty; 'gameStringProperty': LocalizedStringProperty; }; - 'numberSentenceStringProperty': LocalizedStringProperty; + 'numberPhraseStringProperty': LocalizedStringProperty; + 'numberPhraseHelpTextStringProperty': LocalizedStringProperty; 'numberBondStringProperty': LocalizedStringProperty; + 'barModelStringProperty': LocalizedStringProperty; 'equationStringProperty': LocalizedStringProperty; - 'decompositionNumberSentencePatternStringProperty': LocalizedStringProperty; + 'decompositionNumberPhrasePatternStringProperty': LocalizedStringProperty; 'decompositionNumberPhraseSpeechPatternStringProperty': LocalizedStringProperty; - 'sumNumberSentencePatternStringProperty': LocalizedStringProperty; + 'sumNumberPhrasePatternStringProperty': LocalizedStringProperty; 'sumNumberPhraseSpeechPatternStringProperty': LocalizedStringProperty; 'aNumberStringProperty': LocalizedStringProperty; 'someNumberStringProperty': LocalizedStringProperty; @@ -38,24 +40,29 @@ type StringsType = { 'totalStringProperty': LocalizedStringProperty; 'automaticallyHearPhraseStringProperty': LocalizedStringProperty; 'automaticallyHearPhraseDescriptionStringProperty': LocalizedStringProperty; - 'hearNumberSentenceStringProperty': LocalizedStringProperty; - 'organizeObjectsStringProperty': LocalizedStringProperty; - 'organizeObjectsHelpTextStringProperty': LocalizedStringProperty; + 'hearNumberPhraseStringProperty': LocalizedStringProperty; + 'organizeObjectsPatternStringProperty': LocalizedStringProperty; + 'organizeObjectsHelpTextPatternStringProperty': LocalizedStringProperty; 'swapAddendsStringProperty': LocalizedStringProperty; - 'makesAreaVisibleStringProperty': LocalizedStringProperty; - 'firstAddendNoJumpStringProperty': LocalizedStringProperty; - 'firstAddendJumpStringProperty': LocalizedStringProperty; - 'sceneSelectionRadioButtonGroupStringProperty': LocalizedStringProperty; + 'showOrHideAddendStringProperty': LocalizedStringProperty; + 'showOrHideAddendsStringProperty': LocalizedStringProperty; + 'totalNumberPatternStringProperty': LocalizedStringProperty; + 'chooseTotalHelpTextStringProperty': LocalizedStringProperty; 'applesStringProperty': LocalizedStringProperty; 'soccerBallsStringProperty': LocalizedStringProperty; 'butterfliesStringProperty': LocalizedStringProperty; - 'oneCardsStringProperty': LocalizedStringProperty; + 'onesStringProperty': LocalizedStringProperty; 'kittensStringProperty': LocalizedStringProperty; 'beadsStringProperty': LocalizedStringProperty; + 'beadsOnAWireStringProperty': LocalizedStringProperty; 'numberLineStringProperty': LocalizedStringProperty; 'representationTypeStringProperty': LocalizedStringProperty; + 'representationTypeHelpTextStringProperty': LocalizedStringProperty; 'locationCountingObjectsStringProperty': LocalizedStringProperty; 'numberLineSliderStringProperty': LocalizedStringProperty; + 'countOnStringProperty': LocalizedStringProperty; + 'countFromZeroStringProperty': LocalizedStringProperty; + 'totalCheckboxHelpTextStringProperty': LocalizedStringProperty; }; const NumberPairsStrings = getStringModule( 'NUMBER_PAIRS' ) as StringsType; diff --git a/js/common/model/RepresentationType.ts b/js/common/model/RepresentationType.ts index e4fddc9..06a75a7 100644 --- a/js/common/model/RepresentationType.ts +++ b/js/common/model/RepresentationType.ts @@ -58,7 +58,7 @@ export default class RepresentationType extends EnumerationValue { ); public static readonly ONE_CARDS = new RepresentationType( 'oneCards', - NumberPairsStrings.oneCardsStringProperty, + NumberPairsStrings.onesStringProperty, NumberPairsColors.locationSumColorProperty, NumberPairsColors.locationLeftAddendColorProperty, NumberPairsColors.locationRightAddendColorProperty, diff --git a/js/common/view/BeadsOnWireNode.ts b/js/common/view/BeadsOnWireNode.ts index ea50dfd..89a1098 100644 --- a/js/common/view/BeadsOnWireNode.ts +++ b/js/common/view/BeadsOnWireNode.ts @@ -35,6 +35,7 @@ import Vector2Property from '../../../../dot/js/Vector2Property.js'; import BeadManager from '../model/BeadManager.js'; import isResettingAllProperty from '../../../../scenery-phet/js/isResettingAllProperty.js'; import isSettingPhetioStateProperty from '../../../../tandem/js/isSettingPhetioStateProperty.js'; +import NumberPairsStrings from '../../NumberPairsStrings.js'; const BEAD_WIDTH = BeadManager.BEAD_WIDTH; const WIRE_HEIGHT = 4; @@ -96,7 +97,7 @@ export default class BeadsOnWireNode extends Node { const options = optionize()( { children: [ wire, beadSeparator ], excludeInvisibleChildrenFromBounds: true, - accessibleName: 'Beads On a Wire' + accessibleName: NumberPairsStrings.beadsOnAWireStringProperty }, providedOptions ); super( options ); diff --git a/js/common/view/CountingAreaNode.ts b/js/common/view/CountingAreaNode.ts index 9709cb0..653df6e 100644 --- a/js/common/view/CountingAreaNode.ts +++ b/js/common/view/CountingAreaNode.ts @@ -28,6 +28,7 @@ import Animation from '../../../../twixt/js/Animation.js'; import Vector2 from '../../../../dot/js/Vector2.js'; import Dimension2 from '../../../../dot/js/Dimension2.js'; import NumberPairsModel from '../model/NumberPairsModel.js'; +import NumberPairsStrings from '../../NumberPairsStrings.js'; type SelfOptions = { backgroundColorProperty: TReadOnlyProperty; @@ -83,6 +84,7 @@ export default class CountingAreaNode extends Node { } ); const showHideBothAddendsButton = new ShowHideAddendButton( leftAddendVisibleProperty, { + accessibleName: NumberPairsStrings.showOrHideAddendsStringProperty, left: COUNTING_AREA_BOUNDS.minX + COUNTING_AREA_MARGIN, bottom: COUNTING_AREA_BOUNDS.maxY - COUNTING_AREA_MARGIN, secondAddendVisibleProperty: rightAddendVisibleProperty, diff --git a/js/common/view/EquationAccordionBox.ts b/js/common/view/EquationAccordionBox.ts index 2d55193..d42ae42 100644 --- a/js/common/view/EquationAccordionBox.ts +++ b/js/common/view/EquationAccordionBox.ts @@ -18,7 +18,7 @@ import NumberPairsConstants from '../NumberPairsConstants.js'; import NumberRectangle from './NumberRectangle.js'; import TotalRepresentationAccordionBox, { TotalRepresentationAccordionBoxOptions } from './TotalRepresentationAccordionBox.js'; import Dimension2 from '../../../../dot/js/Dimension2.js'; -import NumberSentenceAccordionBox from './NumberSentenceAccordionBox.js'; +import NumberPhraseAccordionBox from './NumberPhraseAccordionBox.js'; type SelfOptions = { addendsOnRight?: boolean; @@ -38,7 +38,7 @@ export default class EquationAccordionBox extends TotalRepresentationAccordionBo addendsOnRight: true, titleNode: titleNode, contentYMargin: 18, - minWidth: NumberSentenceAccordionBox.MIN_WIDTH, // Match the minWidth of the NumberSentenceAccordionBox + minWidth: NumberPhraseAccordionBox.MIN_WIDTH, // Match the minWidth of the NumberPhraseAccordionBox expandedDefaultValue: false }, providedOptions ); diff --git a/js/common/view/NumberBondAccordionBox.ts b/js/common/view/NumberBondAccordionBox.ts index 2e68f2b..bdd2ac2 100644 --- a/js/common/view/NumberBondAccordionBox.ts +++ b/js/common/view/NumberBondAccordionBox.ts @@ -9,7 +9,7 @@ import optionize, { combineOptions } from '../../../../phet-core/js/optionize.js'; import StrictOmit from '../../../../phet-core/js/types/StrictOmit.js'; -import { Text, Node } from '../../../../scenery/js/imports.js'; +import { Node, Text } from '../../../../scenery/js/imports.js'; import numberPairs from '../../numberPairs.js'; import NumberPairsStrings from '../../NumberPairsStrings.js'; import NumberPairsModel from '../model/NumberPairsModel.js'; @@ -30,7 +30,11 @@ type NumberBondAccordionBoxOptions = SelfOptions & StrictOmit { + return numberModelType === NumberModelType.NUMBER_BOND_MODEL ? numberBondString : barModelString; + } ); + const titleNode = new Text( accordionBoxTitleStringProperty, NumberPairsConstants.ACCORDION_BOX_TITLE_OPTIONS ); const options = optionize()( { numberBondNodeOptions: {}, titleNode: titleNode, diff --git a/js/common/view/NumberPairsScreenView.ts b/js/common/view/NumberPairsScreenView.ts index 275f4be..29abd48 100644 --- a/js/common/view/NumberPairsScreenView.ts +++ b/js/common/view/NumberPairsScreenView.ts @@ -39,9 +39,10 @@ import LocaleSwitch from '../../../../number-suite-common/js/common/view/LocaleS import NumberPairsPreferences from '../model/NumberPairsPreferences.js'; import { NumberPairsUtils } from '../model/NumberPairsUtils.js'; import NumberPairsStrings from '../../NumberPairsStrings.js'; +import PatternStringProperty from '../../../../axon/js/PatternStringProperty.js'; type SelfOptions = { - numberSentenceContent: Node; + numberPhraseContent: Node; numberBondContent: Node; equationContent?: Node | null; sceneRange?: Range | null; @@ -82,12 +83,12 @@ export default class NumberPairsScreenView extends ScreenView { /** * Set the layout of the accordion boxes along the top of each screen. */ - const numberSentenceVBox = new VBox( { - children: [ options.numberSentenceContent ], + const numberPhraseVBox = new VBox( { + children: [ options.numberPhraseContent ], spacing: 5, align: 'left' } ); - const numberSentenceAlignBox = new AlignBox( numberSentenceVBox, { + const numberPhraseAlignBox = new AlignBox( numberPhraseVBox, { alignBounds: this.layoutBounds, yMargin: NumberPairsConstants.SCREEN_VIEW_Y_MARGIN, xMargin: NumberPairsConstants.COUNTING_AREA_X_MARGIN, @@ -101,7 +102,7 @@ export default class NumberPairsScreenView extends ScreenView { yAlign: 'top', xAlign: 'center' } ); - this.addChild( numberSentenceAlignBox ); + this.addChild( numberPhraseAlignBox ); this.addChild( numberBondAlignBox ); if ( options.equationContent ) { @@ -132,7 +133,8 @@ export default class NumberPairsScreenView extends ScreenView { */ const speechSynthesisControl = new SpeechSynthesisControl( numberPairsSpeechSynthesisAnnouncer, numberPairsUtteranceQueue, { speechSynthesisButtonOptions: { - accessibleName: NumberPairsStrings.hearNumberSentenceStringProperty + accessibleName: NumberPairsStrings.hearNumberPhraseStringProperty, + helpText: NumberPairsStrings.numberPhraseHelpTextStringProperty }, x: this.layoutBounds.minX + NumberPairsConstants.SCREEN_VIEW_X_MARGIN, y: this.layoutBounds.minY + NumberPairsConstants.SCREEN_VIEW_Y_MARGIN, @@ -142,7 +144,7 @@ export default class NumberPairsScreenView extends ScreenView { const localeSwitch = new LocaleSwitch( NumberPairsPreferences, numberPairsUtteranceQueue, 300, { tandem: options.tandem.createTandem( 'localeSwitch' ) } ); - numberSentenceVBox.addChild( localeSwitch ); + numberPhraseVBox.addChild( localeSwitch ); const tenFrameButtonVisibleProperty = new DerivedProperty( [ model.representationTypeProperty ], countingRepresentation => countingRepresentation === RepresentationType.APPLES || @@ -156,9 +158,15 @@ export default class NumberPairsScreenView extends ScreenView { // we have access to the countingAreaBounds which are defined during construction. const sumTenFrameBounds = COUNTING_AREA_BOUNDS.erodedX( COUNTING_AREA_BOUNDS.width / 3.5 ); const tenFrameBounds = options.sumScreen ? [ sumTenFrameBounds ] : NumberPairsUtils.splitBoundsInHalf( COUNTING_AREA_BOUNDS ); + const organizeObjectsPatternStringProperty = new PatternStringProperty( NumberPairsStrings.organizeObjectsPatternStringProperty, { + representation: model.representationTypeProperty.value.accessibleName + } ); + const organizeObjectsHelpTextPatternStringProperty = new PatternStringProperty( NumberPairsStrings.organizeObjectsHelpTextPatternStringProperty, { + representation: model.representationTypeProperty.value.accessibleName + } ); const tenFrameButton = new TenFrameButton( { - accessibleName: NumberPairsStrings.organizeObjectsStringProperty, - helpText: NumberPairsStrings.organizeObjectsHelpTextStringProperty, + accessibleName: organizeObjectsPatternStringProperty, + helpText: organizeObjectsHelpTextPatternStringProperty, tandem: options.tandem.createTandem( 'tenFrameButton' ), listener: () => { this.interruptSubtreeInput(); @@ -301,8 +309,8 @@ export default class NumberPairsScreenView extends ScreenView { top: COUNTING_AREA_BOUNDS.bottom + COUNTING_AREA_Y_MARGIN, left: COUNTING_AREA_BOUNDS.left, visibleProperty: numberLineVisibleProperty, - valueAAccessibleName: NumberPairsStrings.firstAddendNoJumpStringProperty, - valueBAccessibleName: NumberPairsStrings.firstAddendJumpStringProperty, + valueAAccessibleName: NumberPairsStrings.countOnStringProperty, + valueBAccessibleName: NumberPairsStrings.countFromZeroStringProperty, toggleSwitchOptions: { size: new Dimension2( 36, 18 ) }, @@ -338,7 +346,7 @@ export default class NumberPairsScreenView extends ScreenView { * Add in the rest of the nodes as part of the control area */ this.controlNodes.push( speechSynthesisControl ); - this.controlNodes.push( numberSentenceVBox ); + this.controlNodes.push( numberPhraseVBox ); this.controlNodes.push( options.numberBondContent ); options.equationContent && this.controlNodes.push( options.equationContent ); diff --git a/js/common/view/NumberSentenceAccordionBox.ts b/js/common/view/NumberPhraseAccordionBox.ts similarity index 91% rename from js/common/view/NumberSentenceAccordionBox.ts rename to js/common/view/NumberPhraseAccordionBox.ts index 0ff00da..631417a 100644 --- a/js/common/view/NumberSentenceAccordionBox.ts +++ b/js/common/view/NumberPhraseAccordionBox.ts @@ -53,27 +53,27 @@ NUMBER_TO_WORD_MAP.set( 'someNumber', NumberPairsStrings.someNumberStringPropert NUMBER_TO_WORD_MAP.set( 'anotherNumber', NumberPairsStrings.anotherNumberStringProperty ); type SelfOptions = { - numberSentenceStringProperty: LocalizedStringProperty; + numberPhraseStringProperty: LocalizedStringProperty; numberPhraseSpeechStringProperty: LocalizedStringProperty; speechDataProperty: TProperty; }; -type NumberSentenceAccordionBoxOptions = SelfOptions & StrictOmit; +type NumberPhraseAccordionBoxOptions = SelfOptions & StrictOmit; const LINE_WRAP = 240; -export default class NumberSentenceAccordionBox extends TotalRepresentationAccordionBox { +export default class NumberPhraseAccordionBox extends TotalRepresentationAccordionBox { // We want the accordion box to resize in the Y direction to accommodate the RichText line wrap, however the // width should stay the same. In order to do this we must define and control all options that contribute // to the width of the accordion box. public static readonly MIN_WIDTH = LINE_WRAP + 2 * TotalRepresentationAccordionBox.CONTENT_X_MARGIN + TotalRepresentationAccordionBox.EXPAND_COLLAPSE_SIDE_LENGTH + TotalRepresentationAccordionBox.BUTTON_X_MARGIN; - public constructor( model: NumberPairsModel, providedOptions: NumberSentenceAccordionBoxOptions ) { + public constructor( model: NumberPairsModel, providedOptions: NumberPhraseAccordionBoxOptions ) { - const options = optionize>()( { + const options = optionize>()( { contentXMargin: 20, contentYMargin: 20, contentAlign: 'left', - minWidth: NumberSentenceAccordionBox.MIN_WIDTH, + minWidth: NumberPhraseAccordionBox.MIN_WIDTH, expandedDefaultValue: false }, providedOptions ); @@ -128,17 +128,17 @@ export default class NumberSentenceAccordionBox extends TotalRepresentationAccor const rightAddendDynamicProperty = new DynamicProperty( rightAddendStringProperty ); // Create the PatternStringProperties for primary and secondary locales. - const primaryLocalePatternStringProperty = new PatternStringProperty( options.numberSentenceStringProperty, { + const primaryLocalePatternStringProperty = new PatternStringProperty( options.numberPhraseStringProperty, { total: totalDynamicProperty, leftAddend: leftAddendDynamicProperty, rightAddend: rightAddendDynamicProperty } ); - const secondaryLocaleStringProperty = new DerivedProperty( [ secondLocaleStringsProperty, options.numberSentenceStringProperty ], - ( secondLocaleStrings, numberSentenceString ) => { + const secondaryLocaleStringProperty = new DerivedProperty( [ secondLocaleStringsProperty, options.numberPhraseStringProperty ], + ( secondLocaleStrings, numberPhraseString ) => { const secondLocaleString = secondLocaleStrings[ options.numberPhraseSpeechStringProperty.localizedString.stringKey ]; // If the secondLocaleString is not defined, default to the primary locale string. - return secondLocaleString ? secondLocaleString : numberSentenceString; + return secondLocaleString ? secondLocaleString : numberPhraseString; } ); const secondaryLocalePatternStringProperty = new PatternStringProperty( secondaryLocaleStringProperty, { total: totalDynamicProperty, @@ -148,7 +148,7 @@ export default class NumberSentenceAccordionBox extends TotalRepresentationAccor // This is the final Property that the RichText will listen to. At this point all decisions about what locale // to display based on translation have been filtered down. - const numberSentenceStringProperty = new DerivedProperty( [ + const numberPhraseStringProperty = new DerivedProperty( [ isPrimaryLocaleProperty, primaryLocalePatternStringProperty, secondaryLocalePatternStringProperty @@ -159,7 +159,7 @@ export default class NumberSentenceAccordionBox extends TotalRepresentationAccor let totalHighlight: Rectangle; let leftAddendHighlight: Rectangle; let rightAddendHighlight: Rectangle; - const richText = new RichText( numberSentenceStringProperty, { + const richText = new RichText( numberPhraseStringProperty, { lineWrap: LINE_WRAP, leading: 10, tags: { @@ -240,10 +240,10 @@ export default class NumberSentenceAccordionBox extends TotalRepresentationAccor rightAddendHighlight.fill = color; } ); - options.titleNode = new Text( NumberPairsStrings.numberSentenceStringProperty, NumberPairsConstants.ACCORDION_BOX_TITLE_OPTIONS ); + options.titleNode = new Text( NumberPairsStrings.numberPhraseStringProperty, NumberPairsConstants.ACCORDION_BOX_TITLE_OPTIONS ); super( richText, options ); } } -numberPairs.register( 'NumberSentenceAccordionBox', NumberSentenceAccordionBox ); \ No newline at end of file +numberPairs.register( 'NumberPhraseAccordionBox', NumberPhraseAccordionBox ); \ No newline at end of file diff --git a/js/common/view/RepresentationRadioButtonGroup.ts b/js/common/view/RepresentationRadioButtonGroup.ts index 752e788..d29e6fc 100644 --- a/js/common/view/RepresentationRadioButtonGroup.ts +++ b/js/common/view/RepresentationRadioButtonGroup.ts @@ -40,6 +40,7 @@ export default class RepresentationRadioButtonGroup extends RectangularRadioButt const buttonMargin = 3; const options = optionize()( { accessibleName: NumberPairsStrings.representationTypeStringProperty, + helpText: NumberPairsStrings.representationTypeHelpTextStringProperty, orientation: 'horizontal', radioButtonOptions: { baseColor: Color.WHITE, diff --git a/js/common/view/SceneSelectionRadioButtonGroup.ts b/js/common/view/SceneSelectionRadioButtonGroup.ts index e99dfcd..16bbe7c 100644 --- a/js/common/view/SceneSelectionRadioButtonGroup.ts +++ b/js/common/view/SceneSelectionRadioButtonGroup.ts @@ -17,6 +17,7 @@ import RectangularRadioButtonGroup, { RectangularRadioButtonGroupOptions } from import numberPairs from '../../numberPairs.js'; import NumberPairsScene from '../model/NumberPairsScene.js'; import NumberPairsStrings from '../../NumberPairsStrings.js'; +import PatternStringProperty from '../../../../axon/js/PatternStringProperty.js'; type SelfOptions = { sceneRange: Range; @@ -26,8 +27,12 @@ type SceneSelectionRadioButtonGroupOptions = SelfOptions & RectangularRadioButto export default class SceneSelectionRadioButtonGroup extends RectangularRadioButtonGroup { public constructor( selectedSceneModelProperty: PhetioProperty, sceneModels: NumberPairsScene[], providedOptions: SceneSelectionRadioButtonGroupOptions ) { + const totalNumberPatternStringProperty = new PatternStringProperty( NumberPairsStrings.totalNumberPatternStringProperty, { + value: selectedSceneModelProperty.value.total + } ); const options = optionize()( { - accessibleName: NumberPairsStrings.sceneSelectionRadioButtonGroupStringProperty, + accessibleName: totalNumberPatternStringProperty, + helpText: NumberPairsStrings.chooseTotalHelpTextStringProperty, radioButtonOptions: { size: new Dimension2( 40, 40 ) } diff --git a/js/common/view/ShowHideAddendButton.ts b/js/common/view/ShowHideAddendButton.ts index 5aae100..43e25cf 100644 --- a/js/common/view/ShowHideAddendButton.ts +++ b/js/common/view/ShowHideAddendButton.ts @@ -7,65 +7,59 @@ */ import BooleanProperty from '../../../../axon/js/BooleanProperty.js'; -import DerivedProperty from '../../../../axon/js/DerivedProperty.js'; -import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js'; import Dimension2 from '../../../../dot/js/Dimension2.js'; -import optionize, { combineOptions } from '../../../../phet-core/js/optionize.js'; -import PickRequired from '../../../../phet-core/js/types/PickRequired.js'; -import StrictOmit from '../../../../phet-core/js/types/StrictOmit.js'; -import { Color, Node, Path } from '../../../../scenery/js/imports.js'; -import eyeSlashSolidShape from '../../../../sherpa/js/fontawesome-5/eyeSlashSolidShape.js'; -import eyeSolidShape from '../../../../sherpa/js/fontawesome-5/eyeSolidShape.js'; -import RectangularPushButton, { RectangularPushButtonOptions } from '../../../../sun/js/buttons/RectangularPushButton.js'; +import optionize from '../../../../phet-core/js/optionize.js'; +import { Color } from '../../../../scenery/js/imports.js'; +import EyeToggleButton, { EyeToggleButtonOptions } from '../../../../scenery-phet/js/buttons/EyeToggleButton.js'; import numberPairs from '../../numberPairs.js'; import NumberPairsConstants from '../NumberPairsConstants.js'; -import NumberPairsStrings from '../../NumberPairsStrings.js'; +import Multilink from '../../../../axon/js/Multilink.js'; +import WithRequired from '../../../../phet-core/js/types/WithRequired.js'; type SelfOptions = { secondAddendVisibleProperty?: BooleanProperty | null; }; -type ShowHideAddendButtonOptions = SelfOptions & PickRequired & - StrictOmit; -export default class ShowHideAddendButton extends RectangularPushButton { +type ShowHideAddendButtonOptions = SelfOptions & WithRequired; +export default class ShowHideAddendButton extends EyeToggleButton { public constructor( addendVisibleProperty: BooleanProperty, providedOptions: ShowHideAddendButtonOptions ) { - const initialOptions = optionize()( { - accessibleName: NumberPairsStrings.makesAreaVisibleStringProperty, + const options = optionize()( { size: new Dimension2( NumberPairsConstants.RECTANGULAR_PUSH_BUTTON_OPTIONS.size.width, 40 ), secondAddendVisibleProperty: null, baseColor: Color.WHITE }, providedOptions ); - let addendToggleVisibleProperty: TReadOnlyProperty = addendVisibleProperty; - if ( initialOptions.secondAddendVisibleProperty ) { - addendToggleVisibleProperty = DerivedProperty.and( [ addendVisibleProperty, initialOptions.secondAddendVisibleProperty ] ); - } + let addendToggleVisibleProperty = addendVisibleProperty; + if ( options.secondAddendVisibleProperty ) { + addendToggleVisibleProperty = new BooleanProperty( addendVisibleProperty.value && options.secondAddendVisibleProperty.value, { + reentrant: true, + tandem: options.tandem.createTandem( 'doubleVisibleProperty' ) + } ); + + // Track if our addend visible properties are updating to avoid circular updates. + let updatingAddendVisibleProperties = false; + addendToggleVisibleProperty.link( value => { + if ( !updatingAddendVisibleProperties ) { + updatingAddendVisibleProperties = true; - const options = combineOptions( { - listener: () => { - if ( !addendToggleVisibleProperty.value && initialOptions.secondAddendVisibleProperty ) { - addendVisibleProperty.value = false; - initialOptions.secondAddendVisibleProperty.value = false; + // No matter what the addendToggleVisibleProperty is set to, the other Properties must follow suit. + addendVisibleProperty.value = value; + options.secondAddendVisibleProperty!.value = value; + updatingAddendVisibleProperties = false; } - addendVisibleProperty.toggle(); - initialOptions.secondAddendVisibleProperty && initialOptions.secondAddendVisibleProperty.toggle(); - } - }, initialOptions ); - const eye = new Path( eyeSolidShape, { - fill: Color.BLACK, - visibleProperty: addendToggleVisibleProperty - } ); - const eyeSlash = new Path( eyeSlashSolidShape, { - fill: Color.BLACK, - visibleProperty: DerivedProperty.not( addendToggleVisibleProperty ) - } ); - options.content = new Node( { - children: [ eye, eyeSlash ], - excludeInvisibleChildrenFromBounds: true // so that the parent respects centering of each icon when visible. - } ); + } ); - super( options ); + // If either addendVisibleProperty or secondAddendVisibleProperty changes, update the addendToggleVisibleProperty. + Multilink.multilink( [ addendVisibleProperty, options.secondAddendVisibleProperty ], ( addendVisible, secondAddendVisible ) => { + if ( !updatingAddendVisibleProperties ) { + updatingAddendVisibleProperties = true; + addendToggleVisibleProperty.set( addendVisible && secondAddendVisible ); + updatingAddendVisibleProperties = false; + } + } ); + } + super( addendToggleVisibleProperty, options ); } } diff --git a/js/intro/view/IntroScreenView.ts b/js/intro/view/IntroScreenView.ts index 8c418e1..b8d87a0 100644 --- a/js/intro/view/IntroScreenView.ts +++ b/js/intro/view/IntroScreenView.ts @@ -12,7 +12,7 @@ import StrictOmit from '../../../../phet-core/js/types/StrictOmit.js'; import NumberPairsConstants from '../../common/NumberPairsConstants.js'; import DecompositionScreenView, { DecompositionScreenViewOptions } from '../../common/view/DecompositionScreenView.js'; import NumberBondAccordionBox from '../../common/view/NumberBondAccordionBox.js'; -import NumberSentenceAccordionBox from '../../common/view/NumberSentenceAccordionBox.js'; +import NumberPhraseAccordionBox from '../../common/view/NumberPhraseAccordionBox.js'; import numberPairs from '../../numberPairs.js'; import NumberPairsStrings from '../../NumberPairsStrings.js'; import IntroModel from '../model/IntroModel.js'; @@ -22,7 +22,7 @@ type SelfOptions = { //TODO add options that are specific to IntroScreenView here }; -type IntroScreenViewOptions = SelfOptions & StrictOmit +type IntroScreenViewOptions = SelfOptions & StrictOmit & PickRequired; @@ -31,11 +31,11 @@ export default class IntroScreenView extends DecompositionScreenView { public constructor( model: IntroModel, providedOptions: IntroScreenViewOptions ) { const options = optionize()( { - numberSentenceContent: new NumberSentenceAccordionBox( model, { - numberSentenceStringProperty: NumberPairsStrings.decompositionNumberSentencePatternStringProperty, + numberPhraseContent: new NumberPhraseAccordionBox( model, { + numberPhraseStringProperty: NumberPairsStrings.decompositionNumberPhrasePatternStringProperty, numberPhraseSpeechStringProperty: NumberPairsStrings.decompositionNumberPhraseSpeechPatternStringProperty, speechDataProperty: numberPairsUtteranceQueue.introScreenSpeechDataProperty, - tandem: providedOptions.tandem.createTandem( 'numberSentenceAccordionBox' ) + tandem: providedOptions.tandem.createTandem( 'numberPhraseAccordionBox' ) } ), numberBondContent: new NumberBondAccordionBox( model, { tandem: providedOptions.tandem.createTandem( 'numberBondAccordionBox' ) diff --git a/js/intro/view/SplitCountingAreaNode.ts b/js/intro/view/SplitCountingAreaNode.ts index c77d292..7b924ed 100644 --- a/js/intro/view/SplitCountingAreaNode.ts +++ b/js/intro/view/SplitCountingAreaNode.ts @@ -21,6 +21,7 @@ import NumberPairsConstants from '../../common/NumberPairsConstants.js'; import ShowHideAddendButton from '../../common/view/ShowHideAddendButton.js'; import numberPairs from '../../numberPairs.js'; import { NumberPairsUtils } from '../../common/model/NumberPairsUtils.js'; +import NumberPairsStrings from '../../NumberPairsStrings.js'; const LEFT_ADDEND_COLOR_PROPERTY = NumberPairsColors.locationLeftAddendColorProperty; const RIGHT_ADDEND_COLOR_PROPERTY = NumberPairsColors.locationRightAddendColorProperty; @@ -96,11 +97,13 @@ export default class SplitCountingAreaNode extends Node { super( options ); const leftShowHideAddendButton = new ShowHideAddendButton( leftAddendVisibleProperty, { + accessibleName: NumberPairsStrings.showOrHideAddendStringProperty, left: countingAreaBounds.minX + COUNTING_AREA_MARGIN, bottom: countingAreaBounds.maxY - COUNTING_AREA_MARGIN, tandem: options.tandem.createTandem( 'leftShowHideAddendButton' ) } ); const rightShowHideAddendButton = new ShowHideAddendButton( rightAddendVisibleProperty, { + accessibleName: NumberPairsStrings.showOrHideAddendStringProperty, right: countingAreaBounds.maxX - COUNTING_AREA_MARGIN, bottom: countingAreaBounds.maxY - COUNTING_AREA_MARGIN, tandem: options.tandem.createTandem( 'rightShowHideAddendButton' ) diff --git a/js/sum/view/SumScreenView.ts b/js/sum/view/SumScreenView.ts index 002c44a..6ce9f46 100644 --- a/js/sum/view/SumScreenView.ts +++ b/js/sum/view/SumScreenView.ts @@ -14,7 +14,7 @@ import NumberPairsConstants from '../../common/NumberPairsConstants.js'; import EquationAccordionBox from '../../common/view/EquationAccordionBox.js'; import NumberBondAccordionBox from '../../common/view/NumberBondAccordionBox.js'; import NumberPairsScreenView, { NumberPairsScreenViewOptions } from '../../common/view/NumberPairsScreenView.js'; -import NumberSentenceAccordionBox from '../../common/view/NumberSentenceAccordionBox.js'; +import NumberPhraseAccordionBox from '../../common/view/NumberPhraseAccordionBox.js'; import numberPairs from '../../numberPairs.js'; import NumberPairsStrings from '../../NumberPairsStrings.js'; import SumModel from '../model/SumModel.js'; @@ -24,7 +24,7 @@ import Checkbox from '../../../../sun/js/Checkbox.js'; type SelfOptions = EmptySelfOptions; -type SumScreenViewOptions = SelfOptions & StrictOmit +type SumScreenViewOptions = SelfOptions & StrictOmit & PickRequired; const COUNTING_AREA_BOUNDS = NumberPairsConstants.COUNTING_AREA_BOUNDS; @@ -38,11 +38,11 @@ export default class SumScreenView extends NumberPairsScreenView { const options = optionize()( { sumScreen: true, - numberSentenceContent: new NumberSentenceAccordionBox( model, { - numberSentenceStringProperty: NumberPairsStrings.sumNumberSentencePatternStringProperty, + numberPhraseContent: new NumberPhraseAccordionBox( model, { + numberPhraseStringProperty: NumberPairsStrings.sumNumberPhrasePatternStringProperty, numberPhraseSpeechStringProperty: NumberPairsStrings.sumNumberPhraseSpeechPatternStringProperty, speechDataProperty: numberPairsUtteranceQueue.sumScreenSpeechDataProperty, - tandem: providedOptions.tandem.createTandem( 'numberSentenceAccordionBox' ) + tandem: providedOptions.tandem.createTandem( 'numberPhraseAccordionBox' ) } ), numberBondContent: new NumberBondAccordionBox( model, { numberBondNodeOptions: { @@ -65,6 +65,7 @@ export default class SumScreenView extends NumberPairsScreenView { const horizontalCheckboxSpacing = 35; this.totalCheckbox = new Checkbox( model.totalVisibleProperty, new Text( NumberPairsStrings.totalStringProperty, NumberPairsConstants.CHECKBOX_LABEL_OPTIONS ), { + helpText: NumberPairsStrings.totalCheckboxHelpTextStringProperty, bottom: COUNTING_AREA_BOUNDS.top - NumberPairsConstants.COUNTING_AREA_CHECKBOX_MARGIN, left: COUNTING_AREA_BOUNDS.right - NumberPairsConstants.CHECKBOX_LABEL_OPTIONS.maxWidth * 2 - horizontalCheckboxSpacing, tandem: providedOptions.tandem.createTandem( 'totalCheckbox' ) diff --git a/js/ten/view/TenScreenView.ts b/js/ten/view/TenScreenView.ts index 7a2f273..f05a29b 100644 --- a/js/ten/view/TenScreenView.ts +++ b/js/ten/view/TenScreenView.ts @@ -13,14 +13,14 @@ import NumberPairsConstants from '../../common/NumberPairsConstants.js'; import DecompositionScreenView, { DecompositionScreenViewOptions } from '../../common/view/DecompositionScreenView.js'; import EquationAccordionBox from '../../common/view/EquationAccordionBox.js'; import NumberBondAccordionBox from '../../common/view/NumberBondAccordionBox.js'; -import NumberSentenceAccordionBox from '../../common/view/NumberSentenceAccordionBox.js'; +import NumberPhraseAccordionBox from '../../common/view/NumberPhraseAccordionBox.js'; import numberPairs from '../../numberPairs.js'; import NumberPairsStrings from '../../NumberPairsStrings.js'; import TenModel from '../model/TenModel.js'; import numberPairsUtteranceQueue from '../../common/view/numberPairsUtteranceQueue.js'; type SelfOptions = EmptySelfOptions; -type TenScreenViewOptions = SelfOptions & StrictOmit +type TenScreenViewOptions = SelfOptions & StrictOmit & PickRequired; export default class TenScreenView extends DecompositionScreenView { @@ -28,11 +28,11 @@ export default class TenScreenView extends DecompositionScreenView { public constructor( model: TenModel, providedOptions: TenScreenViewOptions ) { const options = optionize()( { - numberSentenceContent: new NumberSentenceAccordionBox( model, { - numberSentenceStringProperty: NumberPairsStrings.decompositionNumberSentencePatternStringProperty, + numberPhraseContent: new NumberPhraseAccordionBox( model, { + numberPhraseStringProperty: NumberPairsStrings.decompositionNumberPhrasePatternStringProperty, numberPhraseSpeechStringProperty: NumberPairsStrings.decompositionNumberPhraseSpeechPatternStringProperty, speechDataProperty: numberPairsUtteranceQueue.tenScreenSpeechDataProperty, - tandem: providedOptions.tandem.createTandem( 'numberSentenceAccordionBox' ) + tandem: providedOptions.tandem.createTandem( 'numberPhraseAccordionBox' ) } ), numberBondContent: new NumberBondAccordionBox( model, { tandem: providedOptions.tandem.createTandem( 'numberBondAccordionBox' ) diff --git a/js/twenty/view/TwentyScreenView.ts b/js/twenty/view/TwentyScreenView.ts index bedc738..585f78e 100644 --- a/js/twenty/view/TwentyScreenView.ts +++ b/js/twenty/view/TwentyScreenView.ts @@ -13,7 +13,7 @@ import NumberPairsConstants from '../../common/NumberPairsConstants.js'; import DecompositionScreenView, { DecompositionScreenViewOptions } from '../../common/view/DecompositionScreenView.js'; import EquationAccordionBox from '../../common/view/EquationAccordionBox.js'; import NumberBondAccordionBox from '../../common/view/NumberBondAccordionBox.js'; -import NumberSentenceAccordionBox from '../../common/view/NumberSentenceAccordionBox.js'; +import NumberPhraseAccordionBox from '../../common/view/NumberPhraseAccordionBox.js'; import numberPairs from '../../numberPairs.js'; import NumberPairsStrings from '../../NumberPairsStrings.js'; import TwentyModel from '../model/TwentyModel.js'; @@ -23,7 +23,7 @@ type SelfOptions = { //TODO add options that are specific to TwentyScreenView here }; -type TwentyScreenViewOptions = SelfOptions & StrictOmit +type TwentyScreenViewOptions = SelfOptions & StrictOmit & PickRequired; export default class TwentyScreenView extends DecompositionScreenView { @@ -31,11 +31,11 @@ export default class TwentyScreenView extends DecompositionScreenView { public constructor( model: TwentyModel, providedOptions: TwentyScreenViewOptions ) { const options = optionize()( { - numberSentenceContent: new NumberSentenceAccordionBox( model, { - numberSentenceStringProperty: NumberPairsStrings.decompositionNumberSentencePatternStringProperty, + numberPhraseContent: new NumberPhraseAccordionBox( model, { + numberPhraseStringProperty: NumberPairsStrings.decompositionNumberPhrasePatternStringProperty, numberPhraseSpeechStringProperty: NumberPairsStrings.decompositionNumberPhraseSpeechPatternStringProperty, speechDataProperty: numberPairsUtteranceQueue.twentyScreenSpeechDataProperty, - tandem: providedOptions.tandem.createTandem( 'numberSentenceAccordionBox' ) + tandem: providedOptions.tandem.createTandem( 'numberPhraseAccordionBox' ) } ), numberBondContent: new NumberBondAccordionBox( model, { tandem: providedOptions.tandem.createTandem( 'numberBondAccordionBox' ) diff --git a/number-pairs-strings_en.json b/number-pairs-strings_en.json index 3fe2516..b4784a2 100644 --- a/number-pairs-strings_en.json +++ b/number-pairs-strings_en.json @@ -17,22 +17,28 @@ "screen.game": { "value": "Game" }, - "numberSentence": { - "value": "Number Sentence" + "numberPhrase": { + "value": "Number Phrase" + }, + "numberPhraseHelpText": { + "value": "Read number phrase aloud." }, "numberBond": { "value": "Number Bond" }, + "barModel": { + "value": "Bar Model" + }, "equation": { "value": "Equation" }, - "decompositionNumberSentencePattern": { + "decompositionNumberPhrasePattern": { "value": "{{total}} can be decomposed into {{leftAddend}} and {{rightAddend}}" }, "decompositionNumberPhraseSpeechPattern": { "value": "{{total}} can be decomposed into {{leftAddend}} and {{rightAddend}}" }, - "sumNumberSentencePattern": { + "sumNumberPhrasePattern": { "value": "{{leftAddend}} plus {{rightAddend}} equals {{total}}" }, "sumNumberPhraseSpeechPattern": { @@ -65,29 +71,29 @@ "automaticallyHearPhraseDescription": { "value": "Hear the phrase update automatically as you interact." }, - "hearNumberSentence": { + "hearNumberPhrase": { "value": "Hear Number Sentence" }, - "organizeObjects": { - "value": "Organize Objects" + "organizeObjectsPattern": { + "value": "Organize {{representation}}" }, - "organizeObjectsHelpText": { - "value": "Organizes objects into groups of five." + "organizeObjectsHelpTextPattern": { + "value": "Organize {{representation}} into groups of five." }, "swapAddends": { "value": "Swap Addends" }, - "makesAreaVisible": { - "value": "Makes area visible." + "showOrHideAddend": { + "value": "Show or Hide Addend" }, - "firstAddendNoJump": { - "value": "First Addend No Jump" + "showOrHideAddends": { + "value": "Show or Hide Addends" }, - "firstAddendJump": { - "value": "First Addend Jump" + "totalNumberPattern": { + "value": "Total Number {{value}}" }, - "sceneSelectionRadioButtonGroup": { - "value": "Scene Selection Radio Button Group" + "chooseTotalHelpText": { + "value": "Choose total for counting area." }, "apples": { "value": "Apples" @@ -98,8 +104,8 @@ "butterflies": { "value": "Butterflies" }, - "oneCards": { - "value": "One Cards" + "ones": { + "value": "Ones" }, "kittens": { "value": "Kittens" @@ -107,16 +113,31 @@ "beads": { "value": "Beads" }, + "beadsOnAWire": { + "value": "Beads on a Wire" + }, "numberLine": { "value": "Number Line" }, "representationType": { "value": "Representation Type" }, + "representationTypeHelpText": { + "value": "Choose representation for counting area." + }, "locationCountingObjects": { "value": "Location Counting Objects" }, "numberLineSlider": { "value": "Number Line Slider" + }, + "countOn": { + "value": "Count On" + }, + "countFromZero": { + "value": "Count from Zero" + }, + "totalCheckboxHelpText": { + "value": "Show or hide the sum of the two addends." } } \ No newline at end of file