Skip to content

Commit

Permalink
convert to TypeScript, #80
Browse files Browse the repository at this point in the history
  • Loading branch information
pixelzoom committed Mar 1, 2023
1 parent 34ba7b2 commit 0601ee0
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 58 deletions.
51 changes: 28 additions & 23 deletions js/common/view/NumberNode.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,52 @@
// Copyright 2014-2023, University of Colorado Boulder

// @ts-nocheck
/**
* Displays a dynamic numeric value.
*
* @author Chris Malley (PixelZoom, Inc.)
*/

import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js';
import Utils from '../../../../dot/js/Utils.js';
import merge from '../../../../phet-core/js/merge.js';
import { Text } from '../../../../scenery/js/imports.js';
import optionize from '../../../../phet-core/js/optionize.js';
import PickOptional from '../../../../phet-core/js/types/PickOptional.js';
import { NodeTranslationOptions, Text, TextOptions } from '../../../../scenery/js/imports.js';
import reactantsProductsAndLeftovers from '../../reactantsProductsAndLeftovers.js';

type SelfOptions = {
decimalPlaces?: number; // number of decimal places to be displayed
};

type NumberNodeOptions = SelfOptions & NodeTranslationOptions & PickOptional<TextOptions, 'font'>;

export default class NumberNode extends Text {

/**
* @param {Property.<number>} numberProperty
* @param {Object} [options]
*/
constructor( numberProperty, options ) {
private readonly disposeNumberNode: () => void;

public constructor( numberProperty: TReadOnlyProperty<number>, providedOptions?: NumberNodeOptions ) {

options = merge( {
decimalPlaces: 0 // number of decimal places to be displayed
}, options );
const options = optionize<NumberNodeOptions, SelfOptions, TextOptions>()( {

super( '' );
// SelfOptions
decimalPlaces: 0
}, providedOptions );

// @private update the displayed number
this.numberPropertyObserver = value => {
super( '', options );

const numberPropertyObserver = ( value: number ) => {
this.text = Utils.toFixed( value, options.decimalPlaces );
};
this.numberProperty = numberProperty; // @private
this.numberProperty.link( this.numberPropertyObserver ); // must be unlinked in dispose
numberProperty.link( numberPropertyObserver ); // must be unlinked in dispose

this.mutate( options );
this.disposeNumberNode = () => {
if ( numberProperty.hasListener( numberPropertyObserver ) ) {
numberProperty.unlink( numberPropertyObserver );
}
};
}

/**
* @public
* @override
*/
dispose() {
this.numberProperty.unlink( this.numberPropertyObserver );
public override dispose(): void {
this.disposeNumberNode();
super.dispose();
}
}
Expand Down
27 changes: 18 additions & 9 deletions js/common/view/RightArrowNode.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
// Copyright 2014-2023, University of Colorado Boulder

// @ts-nocheck
/**
* An arrow that points from left to right, used in equations to point from reactants to products.
*
* @author Chris Malley (PixelZoom, Inc.)
*/

import merge from '../../../../phet-core/js/merge.js';
import ArrowNode from '../../../../scenery-phet/js/ArrowNode.js';
import optionize from '../../../../phet-core/js/optionize.js';
import PickOptional from '../../../../phet-core/js/types/PickOptional.js';
import ArrowNode, { ArrowNodeOptions } from '../../../../scenery-phet/js/ArrowNode.js';
import { NodeTranslationOptions } from '../../../../scenery/js/imports.js';
import reactantsProductsAndLeftovers from '../../reactantsProductsAndLeftovers.js';

type SelfOptions = {
length?: number;
};

type RightArrowNodeOptions = SelfOptions & NodeTranslationOptions &
PickOptional<ArrowNodeOptions, 'fill' | 'stroke' | 'scale'>;

export default class RightArrowNode extends ArrowNode {

/**
* @param {Object} [options]
*/
constructor( options ) {
public constructor( providedOptions?: RightArrowNodeOptions ) {

options = merge( {
const options = optionize<RightArrowNodeOptions, SelfOptions, ArrowNodeOptions>()( {

// SelfOptions
length: 70,

// ArrowNodeOptions
tailWidth: 15,
headWidth: 35,
headHeight: 30
}, options );
}, providedOptions );

super( 0, 0, options.length, 0, options );
}
Expand Down
56 changes: 30 additions & 26 deletions js/common/view/SubstanceIcon.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright 2014-2023, University of Colorado Boulder

// @ts-nocheck
/**
* Displays a Substance's icon, which may change dynamically.
*
Expand All @@ -23,43 +22,48 @@
* @author Chris Malley (PixelZoom, Inc.)
*/

import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js';
import Vector2 from '../../../../dot/js/Vector2.js';
import { Node } from '../../../../scenery/js/imports.js';
import optionize, { EmptySelfOptions } from '../../../../phet-core/js/optionize.js';
import { Node, NodeOptions, NodeTranslationOptions } from '../../../../scenery/js/imports.js';
import reactantsProductsAndLeftovers from '../../reactantsProductsAndLeftovers.js';

type SelfOptions = EmptySelfOptions;

type SubstanceIconOptions = SelfOptions & NodeTranslationOptions;

export default class SubstanceIcon extends Node {

/**
* @param {Property.<Node>} iconProperty
* @param {Object} [options]
*/
constructor( iconProperty, options ) {
private readonly disposeSubstanceIcon: () => void;

public constructor( iconProperty: TReadOnlyProperty<Node>, providedOptions?: SubstanceIconOptions ) {

super();
const options = optionize<SubstanceIconOptions, SelfOptions, NodeOptions>()( {}, providedOptions );

// @private Add an additional wrapper, so that we can maintain the node's center.
this.wrapperNode = new Node();
this.addChild( this.wrapperNode );
// Add a wrapper, so that we can keep the icon centered and not run afoul of scenery DAG feature.
const wrapperNode = new Node();

this.iconProperty = iconProperty; // @private
this.iconPropertyObserver = icon => { // @private
this.wrapperNode.removeAllChildren();
// icon must be removed in dispose, since scenery children keep a reference to their parents
this.wrapperNode.addChild( icon );
this.wrapperNode.center = Vector2.ZERO;
const iconPropertyObserver = ( icon: Node ) => {
wrapperNode.removeAllChildren();
wrapperNode.addChild( icon ); // icon must be removed in dispose, since scenery children keep a reference to their parents
wrapperNode.center = Vector2.ZERO;
};
this.iconProperty.link( this.iconPropertyObserver ); // must be unlinked in dispose
iconProperty.link( iconPropertyObserver ); // must be unlinked in dispose

this.mutate( options );
options.children = [ wrapperNode ];

super( options );

this.disposeSubstanceIcon = () => {
if ( iconProperty.hasListener( iconPropertyObserver ) ) {
iconProperty.unlink( iconPropertyObserver );
}
wrapperNode.removeAllChildren(); // to disconnect from icon
};
}

/**
* @public
* @override
*/
dispose() {
this.iconProperty.unlink( this.iconPropertyObserver );
this.wrapperNode.removeAllChildren(); // to disconnect from icon
public override dispose(): void {
this.disposeSubstanceIcon();
super.dispose();
}
}
Expand Down

0 comments on commit 0601ee0

Please sign in to comment.