Skip to content

Commit

Permalink
change UI for electromagnet (MAJOR CHANGE), #163
Browse files Browse the repository at this point in the history
  • Loading branch information
pixelzoom committed May 7, 2024
1 parent e9e6c13 commit c415010
Show file tree
Hide file tree
Showing 14 changed files with 432 additions and 267 deletions.
6 changes: 6 additions & 0 deletions faradays-electromagnetic-lab-strings_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@
"acPowerSupply": {
"value": "AC Power Supply"
},
"dcPowerSupply": {
"value": "DC Power Supply"
},
"batteryVoltage": {
"value": "Battery Voltage"
},
"pattern.valuePercent": {
"value": "{{value}}%"
},
Expand Down
2 changes: 2 additions & 0 deletions js/FaradaysElectromagneticLabStrings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ type StringsType = {
'electromagnetStringProperty': LocalizedStringProperty;
'currentSourceStringProperty': LocalizedStringProperty;
'acPowerSupplyStringProperty': LocalizedStringProperty;
'dcPowerSupplyStringProperty': LocalizedStringProperty;
'batteryVoltageStringProperty': LocalizedStringProperty;
'pattern': {
'valuePercentStringProperty': LocalizedStringProperty;
'valueUnitsStringProperty': LocalizedStringProperty;
Expand Down
6 changes: 1 addition & 5 deletions js/common/FELColors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,14 +255,10 @@ const FELColors = {
default: Color.grayColor( 200 )
} ),

acPowerSupplyDisplayColorProperty: new ProfileColorProperty( faradaysElectromagneticLab, 'acPowerSupplyDisplayColor', {
acPowerSupplyChartProperty: new ProfileColorProperty( faradaysElectromagneticLab, 'acPowerSupplyDisplayColor', {
default: 'black'
} ),

acPowerSupplyTextColorProperty: new ProfileColorProperty( faradaysElectromagneticLab, 'acPowerSupplyTextColor', {
default: 'rgb( 0, 255, 0 )'
} ),

acPowerSupplyWaveColorProperty: new ProfileColorProperty( faradaysElectromagneticLab, 'acPowerSupplyWaveColor', {
default: 'rgb( 0, 255, 0 )'
} ),
Expand Down
15 changes: 6 additions & 9 deletions js/common/view/ACNumberControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ import ArrowButton from '../../../../sun/js/buttons/ArrowButton.js';
import faradaysElectromagneticLab from '../../faradaysElectromagneticLab.js';
import PickRequired from '../../../../phet-core/js/types/PickRequired.js';
import PhetFont from '../../../../scenery-phet/js/PhetFont.js';
import FELColors from '../FELColors.js';
import Dimension2 from '../../../../dot/js/Dimension2.js';
import Tandem from '../../../../tandem/js/Tandem.js';
import FELConstants from '../FELConstants.js';

const NUMBER_DISPLAY_FONT = new PhetFont( 12 );
const HORIZONTAL_THUMB_SIZE = new Dimension2( 15, 30 );
const HORIZONTAL_TRACK_SIZE = new Dimension2( 100, 3 );
const SLIDER_STEP = 1; // %

Expand All @@ -51,18 +51,15 @@ export default class ACNumberControl extends NumberControl {
sliderOptions: combineOptions<NumberControlSliderOptions>( {}, FELConstants.PERCENT_SLIDER_OPTIONS, {
constrainValue: ( value: number ) => Utils.roundToInterval( value, SLIDER_STEP ),
orientation: ( providedOptions.orientation === 'horizontal' ) ? Orientation.HORIZONTAL : Orientation.VERTICAL,
thumbSize: ( providedOptions.orientation === 'horizontal' ) ? HORIZONTAL_THUMB_SIZE : HORIZONTAL_THUMB_SIZE.swapped(),
trackSize: ( providedOptions.orientation === 'horizontal' ) ? HORIZONTAL_TRACK_SIZE : HORIZONTAL_TRACK_SIZE.swapped(),
tandem: Tandem.OPT_OUT
} ),
numberDisplayOptions: {
backgroundFill: FELColors.acPowerSupplyDisplayColorProperty,
backgroundStroke: null,
cornerRadius: 3,
xMargin: 8,
yMargin: 5,
xMargin: 6,
yMargin: 3,
textOptions: {
font: NUMBER_DISPLAY_FONT,
fill: FELColors.acPowerSupplyTextColorProperty,
maxWidth: 30
},
numberFormatter: value => StringUtils.fillIn( FaradaysElectromagneticLabStrings.pattern.valuePercentStringProperty, {
Expand All @@ -82,7 +79,7 @@ export default class ACNumberControl extends NumberControl {
function createVerticalLayout( titleNode: Node, numberDisplay: NumberDisplay, slider: Slider, decrementButton: ArrowButton | null, incrementButton: ArrowButton | null ): Node {
return new VBox( {
children: [ numberDisplay, slider ],
spacing: 5,
spacing: 3,
align: 'center',
excludeInvisibleChildrenFromBounds: false
} );
Expand All @@ -91,7 +88,7 @@ function createVerticalLayout( titleNode: Node, numberDisplay: NumberDisplay, sl
function createHorizontalLayout( titleNode: Node, numberDisplay: NumberDisplay, slider: Slider, decrementButton: ArrowButton | null, incrementButton: ArrowButton | null ): Node {
return new HBox( {
children: [ slider, numberDisplay ],
spacing: 5,
spacing: 3,
align: 'center',
excludeInvisibleChildrenFromBounds: false
} );
Expand Down
156 changes: 20 additions & 136 deletions js/common/view/ACPowerSupplyNode.ts
Original file line number Diff line number Diff line change
@@ -1,159 +1,43 @@
// Copyright 2023-2024, University of Colorado Boulder

/**
* ACPowerSupplyNode is the view of the AC power supply. It provides sliders for changing the maximum voltage
* and frequency (as percentages), and depicts the fluctuation of voltage over time as a sine wave.
*
* This is based on ACPowerSupplyGraphic.java in the Java version of this sim.
* ACPowerSupplyNode is view of the AC power supply attached to the electromagnet.
*
* @author Chris Malley (PixelZoom, Inc.)
*/

import faradaysElectromagneticLab from '../../faradaysElectromagneticLab.js';
import { Circle, HBox, Node, Path, Text, VBox } from '../../../../scenery/js/imports.js';
import Vector2 from '../../../../dot/js/Vector2.js';
import { Shape } from '../../../../kite/js/imports.js';
import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js';
import CurrentSource from '../model/CurrentSource.js';
import Tandem from '../../../../tandem/js/Tandem.js';
import ACPowerSupply from '../model/ACPowerSupply.js';
import DerivedProperty from '../../../../axon/js/DerivedProperty.js';
import BooleanIO from '../../../../tandem/js/types/BooleanIO.js';
import FELColors from '../FELColors.js';
import FaradaysElectromagneticLabStrings from '../../FaradaysElectromagneticLabStrings.js';
import Dimension2 from '../../../../dot/js/Dimension2.js';
import FELConstants from '../FELConstants.js';
import VoltageChartNode from './VoltageChartNode.js';
import ACNumberControl from './ACNumberControl.js';
import ShadedRectangle, { ShadedRectangleOptions } from '../../../../scenery-phet/js/ShadedRectangle.js';
import ShadedRectangle from '../../../../scenery-phet/js/ShadedRectangle.js';
import Bounds2 from '../../../../dot/js/Bounds2.js';
import FELColors from '../FELColors.js';
import optionize, { EmptySelfOptions } from '../../../../phet-core/js/optionize.js';
import ACPowerSupplyPanel from './ACPowerSupplyPanel.js';
import { Node, NodeOptions, NodeTranslationOptions } from '../../../../scenery/js/imports.js';

const CORNER_RADIUS = 10;
const BODY_X_MARGIN = 12;
const BODY_Y_MARGIN = 8;
const BODY_OPTIONS: ShadedRectangleOptions = {
lightSource: 'leftTop',
baseColor: FELColors.acPowerSupplyBodyColorProperty,
cornerRadius: CORNER_RADIUS
};

export default class ACPowerSupplyNode extends Node {

public constructor( acPowerSupply: ACPowerSupply, currentSourceProperty: TReadOnlyProperty<CurrentSource>, tandem: Tandem ) {

// Frequency control
const frequencyControl = new ACNumberControl( acPowerSupply.frequencyPercentProperty, {
orientation: 'horizontal',
tandem: tandem.createTandem( 'frequencyControl' )
} );

// Max voltage control
const maxVoltageControl = new ACNumberControl( acPowerSupply.maxVoltagePercentProperty, {
orientation: 'vertical',
tandem: tandem.createTandem( 'maxVoltageControl' )
} );

// Chart of voltage over time
const chartNode = new VoltageChartNode( acPowerSupply, {
viewSize: new Dimension2( 165, 122 )
} );

const chartAndSliders = new HBox( {
children: [
maxVoltageControl,
new VBox( {
align: 'right',
spacing: 8,
children: [ chartNode, frequencyControl ]
} )
],
align: 'top',
spacing: 8
} );
type SelfOptions = EmptySelfOptions;

const titleText = new Text( FaradaysElectromagneticLabStrings.acPowerSupplyStringProperty, {
font: FELConstants.TITLE_FONT,
maxWidth: chartNode.width
} );
type ACPowerSupplyNodeOptions = SelfOptions & NodeTranslationOptions;

const contentNode = new VBox( {
children: [
titleText,
chartAndSliders
],
spacing: 8,
align: 'center'
} );
export default class ACPowerSupplyNode extends Node {

super( {
children: [ contentNode ],
visibleProperty: new DerivedProperty( [ currentSourceProperty ], currentSource => ( currentSource === acPowerSupply ), {
tandem: tandem.createTandem( 'visibleProperty' ),
phetioValueType: BooleanIO
} ),
tandem: tandem,
phetioFeatured: true
} );
public constructor( providedOptions?: ACPowerSupplyNodeOptions ) {

// Body of the AC power supply, sized to fit. Because ShadedRectangle is not resizable, we need to create a new one
// if the size of contentNode is changed by making elements invisible via PhET-iO.
let bodyNode: Node;
contentNode.boundsProperty.link( () => {
if ( bodyNode && this.hasChild( bodyNode ) ) {
this.removeChild( bodyNode );
}
bodyNode = new ShadedRectangle( new Bounds2( 0, 0, contentNode.width + ( 2 * BODY_X_MARGIN ), contentNode.height + ( 2 * BODY_Y_MARGIN ) ), BODY_OPTIONS );
this.addChild( bodyNode );
bodyNode.moveToBack();
contentNode.center = bodyNode.center;
const rectangle = new ShadedRectangle( new Bounds2( 0, 0, 120, 50 ), {
baseColor: FELColors.acPowerSupplyBodyColorProperty,
cornerRadius: 5
} );

// Interrupt interaction when this Node becomes invisible.
this.visibleProperty.lazyLink( visible => !visible && this.interruptSubtreeInput() );

this.addLinkedElement( acPowerSupply );
}

/**
* Creates an icon for the AC power supply. This is the universal symbol for AC power.
*/
public static createIcon( scale = 1 ): Node {

const circle = new Circle( {
radius: 18,
fill: FELColors.acPowerSupplyDisplayColorProperty
} );
const icon = ACPowerSupplyPanel.createIcon();
icon.center = rectangle.center;

// Sine wave symbol
const sineDataSet = createSineDataSet( 0, 25, 25, -8, 1 );
const sineShape = new Shape().moveToPoint( sineDataSet[ 0 ] );
for ( let i = 1; i < sineDataSet.length; i++ ) {
sineShape.lineToPoint( sineDataSet[ i ] );
}
const sinePath = new Path( sineShape, {
stroke: FELColors.acPowerSupplyWaveColorProperty,
lineWidth: 3,
center: circle.center
} );
const options = optionize<ACPowerSupplyNodeOptions, SelfOptions, NodeOptions>()( {

return new Node( {
children: [ circle, sinePath ],
pickable: false,
scale: scale
} );
}
}
// NodeOptions
children: [ rectangle, icon ]
}, providedOptions );

/**
* Creates a data set for a sine wave, an array of Vector2, ordered by ascending x value.
*/
function createSineDataSet( xMin: number, xMax: number, period: number, amplitude: number, delta: number ): Vector2[] {
const dataSet = [];
const frequency = 2 * Math.PI / period;
for ( let x = xMin; x <= xMax; x += delta ) {
dataSet.push( new Vector2( x, amplitude * Math.sin( x * frequency ) ) );
super( options );
}
return dataSet;
}

faradaysElectromagneticLab.register( 'ACPowerSupplyNode', ACPowerSupplyNode );
Loading

0 comments on commit c415010

Please sign in to comment.