diff --git a/js/HomeScreenButton.ts b/js/HomeScreenButton.ts index 65e8c825..4b1b53f0 100644 --- a/js/HomeScreenButton.ts +++ b/js/HomeScreenButton.ts @@ -107,7 +107,7 @@ class HomeScreenButton extends Voicing( VBox ) { assert && assert( screen.nameProperty.value, 'name is required for screen.' ); // text for the button - const text = new Text( screen.nameProperty.value!, { + const text = new Text( screen.nameProperty.value, { tandem: options.tandem.createTandem( 'text' ), textPropertyOptions: { phetioReadOnly: true } // text is updated via screen.nameProperty } ); diff --git a/js/NavigationBarScreenButton.ts b/js/NavigationBarScreenButton.ts index 7ccd09e6..1c41b34c 100644 --- a/js/NavigationBarScreenButton.ts +++ b/js/NavigationBarScreenButton.ts @@ -102,7 +102,7 @@ class NavigationBarScreenButton extends Voicing( Node ) { } ); assert && assert( screen.nameProperty.value, 'screen name should be defined' ); - const text = new Text( screen.nameProperty.value!, { + const text = new Text( screen.nameProperty.value, { font: new PhetFont( 10 ), tandem: options.tandem.createTandem( 'text' ), diff --git a/js/Screen.ts b/js/Screen.ts index 89c49f9a..da3ab390 100644 --- a/js/Screen.ts +++ b/js/Screen.ts @@ -34,6 +34,7 @@ import ScreenView from './ScreenView.js'; import PickRequired from '../../phet-core/js/types/PickRequired.js'; import Multilink from '../../axon/js/Multilink.js'; import TModel from './TModel.js'; +import ReadOnlyProperty from '../../axon/js/ReadOnlyProperty.js'; const screenNamePatternString = joistStrings.a11y.screenNamePattern; const screenSimPatternString = joistStrings.a11y.screenSimPattern; @@ -52,7 +53,7 @@ assert && assert( Math.abs( HOME_SCREEN_ICON_ASPECT_RATIO - HOME_SCREEN_ICON_ASP // Documentation is by the defaults type SelfOptions = { - name?: string | null; + name?: string | ReadOnlyProperty | null; instrumentNameProperty?: boolean; // It would be preferable to support Property solely, but many subtypes are hardcoded to be Color only @@ -80,7 +81,7 @@ class Screen exten public readonly maxDT: number; public readonly activeProperty: BooleanProperty; public readonly descriptionContent: string; - public readonly nameProperty: TReadOnlyProperty; + public readonly nameProperty: Property; public readonly showScreenIconFrameForNavigationBarFill: string | null; public readonly homeScreenIcon: Node | null; @@ -179,13 +180,18 @@ class Screen exten const instrumentNameProperty = options.instrumentNameProperty && options.name; // may be null for single-screen simulations - this.nameProperty = new Property( options.name, { + this.nameProperty = new Property( typeof options.name === 'string' ? options.name : ( options.name ? options.name.value : '' ), { phetioValueType: NullableIO( StringIO ), tandem: instrumentNameProperty ? options.tandem.createTandem( 'nameProperty' ) : Tandem.OPT_OUT, phetioFeatured: true, phetioDocumentation: 'The name of the screen. Changing this value will update the screen name for the screen\'s ' + 'corresponding button on the navigation bar and home screen, if they exist.' } ); + if ( options.name instanceof ReadOnlyProperty ) { + options.name.link( name => { + this.nameProperty.value = name; + } ); + } this.homeScreenIcon = options.homeScreenIcon; this.navigationBarIcon = options.navigationBarIcon; diff --git a/js/Sim.ts b/js/Sim.ts index 1be280ff..426d9a31 100644 --- a/js/Sim.ts +++ b/js/Sim.ts @@ -261,7 +261,7 @@ export default class Sim extends PhetioObject { * @param allSimScreens - the possible screens for the sim in order of declaration (does not include the home screen) * @param [providedOptions] - see below for options */ - public constructor( name: string, allSimScreens: Screen[], providedOptions?: SimOptions ) { + public constructor( name: string | TReadOnlyProperty, allSimScreens: Screen[], providedOptions?: SimOptions ) { window.phetSplashScreenDownloadComplete(); @@ -312,12 +312,18 @@ export default class Sim extends PhetioObject { this.createOptionsDialogContent = options.createOptionsDialogContent; - this.simNameProperty = new StringProperty( name, { + this.simNameProperty = new StringProperty( typeof name === 'string' ? name : name.value, { tandem: Tandem.GENERAL_MODEL.createTandem( 'simNameProperty' ), phetioFeatured: true, phetioDocumentation: 'The name of the sim. Changing this value will update the title text on the navigation bar ' + 'and the title text on the home screen, if it exists.' } ); + if ( typeof name !== 'string' ) { + name.lazyLink( nameString => { + // @ts-ignore Ignoring readonly for now + this.simNameProperty.value = nameString; + } ); + } // playbackModeEnabledProperty cannot be changed after Sim construction has begun, hence this listener is added before // anything else is done, see https://github.com/phetsims/phet-io/issues/1146 @@ -628,9 +634,9 @@ export default class Sim extends PhetioObject { // If the locale query parameter was specified, then we may be running the all.html file, so adjust the title. // See https://github.com/phetsims/chipper/issues/510 - if ( QueryStringMachine.containsKey( 'locale' ) ) { - $( 'title' ).html( name ); - } + this.simNameProperty.link( simName => { + $( 'title' ).html( simName ); + } ); if ( options.preferencesConfiguration ) { diff --git a/js/localeProperty.ts b/js/localeProperty.ts new file mode 100644 index 00000000..88076de4 --- /dev/null +++ b/js/localeProperty.ts @@ -0,0 +1,21 @@ +// Copyright 2022, University of Colorado Boulder + +/** + * A universal locale Property that is accessible independently of the running Sim instance. + * + * @author Jonathan Olson + */ + +import StringProperty from '../../axon/js/StringProperty.js'; +import Tandem from '../../tandem/js/Tandem.js'; +import joist from './joist.js'; + +const localeProperty = new StringProperty( phet.chipper.locale || 'en', { + tandem: Tandem.GENERAL_VIEW.createTandem( 'localeProperty' ), + phetioFeatured: true, + validValues: Object.keys( phet.chipper.strings ) +} ); + +joist.register( 'localeProperty', localeProperty ); + +export default localeProperty;