Skip to content

Commit

Permalink
support floating labels in histogram, do other refactoring, see #52
Browse files Browse the repository at this point in the history
  • Loading branch information
jbphet committed Nov 18, 2024
1 parent dcbc8ae commit 568a8f2
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 68 deletions.
6 changes: 3 additions & 3 deletions js/bloch-sphere/view/BlochSphereScreenView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export default class BlochSphereScreenView extends QuantumMeasurementScreenView
spacing: 10,
center: this.layoutBounds.center,
children: [
new QuantumMeasurementHistogram( leftProperty, rightProperty, new BooleanProperty( true ),
new QuantumMeasurementHistogram( leftProperty, rightProperty,
[
new RichText( 'V', { font: new PhetFont( { size: 17, weight: 'bold' } ) } ),
new RichText( 'H', { font: new PhetFont( { size: 17, weight: 'bold' } ) } )
Expand All @@ -113,7 +113,7 @@ export default class BlochSphereScreenView extends QuantumMeasurementScreenView
visibleProperty: new BooleanProperty( true ),
tandem: Tandem.OPT_OUT
} ),
new QuantumMeasurementHistogram( leftProperty, rightProperty, new BooleanProperty( true ),
new QuantumMeasurementHistogram( leftProperty, rightProperty,
[
new RichText( 'V', { font: new PhetFont( { size: 17, weight: 'bold' } ), fill: QuantumMeasurementColors.verticalPolarizationColorProperty } ),
new RichText( 'H', { font: new PhetFont( { size: 17, weight: 'bold' } ) } )
Expand All @@ -127,7 +127,7 @@ export default class BlochSphereScreenView extends QuantumMeasurementScreenView
visibleProperty: new BooleanProperty( true ),
tandem: Tandem.OPT_OUT
} ),
new QuantumMeasurementHistogram( leftProperty, rightProperty, new BooleanProperty( true ),
new QuantumMeasurementHistogram( leftProperty, rightProperty,
[
new RichText( 'S<sub>z</sub>' + QuantumMeasurementConstants.SPIN_UP_ARROW_CHARACTER, { font: new PhetFont( { size: 17, weight: 'bold' } ) } ),
new RichText( 'S<sub>z</sub>' + QuantumMeasurementConstants.SPIN_DOWN_ARROW_CHARACTER, { font: new PhetFont( { size: 17, weight: 'bold' } ) } )
Expand Down
8 changes: 0 additions & 8 deletions js/coins/view/CoinMeasurementHistogram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
* @author John Blanco, PhET Interactive Simulations
*/

import DerivedProperty from '../../../../axon/js/DerivedProperty.js';
import DerivedStringProperty from '../../../../axon/js/DerivedStringProperty.js';
import Multilink from '../../../../axon/js/Multilink.js';
import NumberProperty from '../../../../axon/js/NumberProperty.js';
Expand Down Expand Up @@ -96,16 +95,9 @@ export default class CoinMeasurementHistogram extends QuantumMeasurementHistogra

coinSet.measuredDataChangedEmitter.addListener( updateNumberProperties );

// Create a Property that controls whether the values should be displayed.
const displayValuesProperty = DerivedProperty.valueEqualsConstant(
coinSet.measurementStateProperty,
'revealed'
);

super(
leftNumberProperty,
rightNumberProperty,
displayValuesProperty,
xAxisLabels as [RichText, RichText],
providedOptions
);
Expand Down
93 changes: 41 additions & 52 deletions js/common/view/QuantumMeasurementHistogram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import optionize, { combineOptions } from '../../../../phet-core/js/optionize.js
import WithRequired from '../../../../phet-core/js/types/WithRequired.js';
import NumberDisplay, { NumberDisplayOptions } from '../../../../scenery-phet/js/NumberDisplay.js';
import PhetFont from '../../../../scenery-phet/js/PhetFont.js';
import { AlignBox, AlignGroup, Color, HBox, Line, Node, NodeOptions, Rectangle, RichText } from '../../../../scenery/js/imports.js';
import { Color, Line, Node, NodeOptions, Rectangle, RichText } from '../../../../scenery/js/imports.js';
import { MAX_COINS } from '../../coins/model/CoinsExperimentSceneModel.js';
import quantumMeasurement from '../../quantumMeasurement.js';
import QuantumMeasurementStrings from '../../QuantumMeasurementStrings.js';
Expand All @@ -37,34 +37,36 @@ type SelfOptions = {
// another at the top of the Y axis. Both will be labeled.
showTickMarks?: boolean;

// Whether the labels should float above the bars (vertical orientation) or beside the bars (horizontal orientation).
floatingLabels?: boolean;

// label for the top tick mark, if present
topTickMarkTextProperty?: TReadOnlyProperty<string>;
};
export type QuantumMeasurementHistogramOptions = SelfOptions & WithRequired<NodeOptions, 'tandem' | 'visibleProperty'>;

const HISTOGRAM_SIZE = new Dimension2( 200, 160 ); // size excluding labels at bottom, in screen coordinates
const RIGHT_HISTOGRAM_BAR_CENTER_X = HISTOGRAM_SIZE.width / 4;
const LEFT_HISTOGRAM_BAR_CENTER_X = -HISTOGRAM_SIZE.width / 4;
const AXIS_STROKE = Color.BLACK;
const AXIS_LINE_WIDTH = 2;
const LABEL_FONT = new PhetFont( { size: 20, weight: 'bold' } );
const TICK_MARK_LENGTH = 20;
const TICK_MARK_FONT = new PhetFont( 14 );
const NUMBER_DISPLAY_RANGE = new Range( 0, MAX_COINS );
const NUMBER_DISPLAY_MAX_WIDTH = HISTOGRAM_SIZE.width / 2 * 0.85;
const FLOATING_LABEL_MARGIN = 5;
export const HISTOGRAM_BAR_WIDTH = HISTOGRAM_SIZE.width / 6;

export default class QuantumMeasurementHistogram extends Node {

protected readonly xAxis: Line;
protected readonly yAxis: Line;

protected readonly leftHistogramBar: Rectangle;
protected readonly rightHistogramBar: Rectangle;

protected readonly maxBarHeight: number;

public constructor( leftNumberProperty: TReadOnlyProperty<number>,
rightNumberProperty: TReadOnlyProperty<number>,
displayValuesProperty: TReadOnlyProperty<boolean>,
providedXAxisLabels: [ RichText, RichText ],
providedOptions: QuantumMeasurementHistogramOptions ) {

Expand All @@ -87,6 +89,7 @@ export default class QuantumMeasurementHistogram extends Node {
rightFillColorProperty: QuantumMeasurementColors.tailsColorProperty,
showTickMarks: true,
topTickMarkTextProperty: new StringProperty( '' ),
floatingLabels: false,
children: [],
numberDisplayOptions: {
align: 'center',
Expand Down Expand Up @@ -204,53 +207,27 @@ export default class QuantumMeasurementHistogram extends Node {
const maxBarHeight = yAxis.height;
const leftFillColorProperty = options.leftFillColorProperty;
const rightFillColorProperty = options.rightFillColorProperty;
const leftHistogramBar = new Rectangle( 0, 0, options.barWidth, maxBarHeight, { fill: leftFillColorProperty } );
const rightHistogramBar = new Rectangle( 0, 0, options.barWidth, maxBarHeight, { fill: rightFillColorProperty } );

const leftAlignGroup = new AlignGroup( { matchVertical: false } );
const rightAlignGroup = new AlignGroup( { matchVertical: false } );

const SPACING = HISTOGRAM_SIZE.width / 4;

const numberDisplays = new HBox( {
children: [
new AlignBox( leftNumberDisplay, { group: leftAlignGroup } ),
new AlignBox( rightNumberDisplay, { group: rightAlignGroup } )
],
centerX: 0,
spacing: SPACING,
bottom: yAxis.top,
visibleProperty: displayValuesProperty
const leftHistogramBar = new Rectangle( 0, 0, options.barWidth, maxBarHeight, {
fill: leftFillColorProperty,
centerX: LEFT_HISTOGRAM_BAR_CENTER_X
} );
const rightHistogramBar = new Rectangle( 0, 0, options.barWidth, maxBarHeight, {
fill: rightFillColorProperty,
centerX: RIGHT_HISTOGRAM_BAR_CENTER_X
} );

// Create the labels for the X axis.
// Create and position the labels for the X axis.
const axisLabelMargin = 6;
const xAxisLeftLabel = providedXAxisLabels[ 0 ];
xAxisLeftLabel.centerX = LEFT_HISTOGRAM_BAR_CENTER_X;
xAxisLeftLabel.top = xAxis.centerY + axisLabelMargin;
const xAxisRightLabel = providedXAxisLabels[ 1 ];
xAxisRightLabel.centerX = RIGHT_HISTOGRAM_BAR_CENTER_X;
xAxisRightLabel.top = xAxis.centerY + axisLabelMargin;

xAxisLeftLabel.rotation = textRotation;
xAxisRightLabel.rotation = textRotation;

const xAxisLabels = new HBox( {
children: [
new AlignBox( xAxisLeftLabel, { group: leftAlignGroup } ),
new AlignBox( xAxisRightLabel, { group: rightAlignGroup } )
],
centerX: 0,
spacing: SPACING,
top: xAxis.centerY + 6
} );
const numberBars = new HBox( {
children: [
new AlignBox( leftHistogramBar, { group: leftAlignGroup } ),
new AlignBox( rightHistogramBar, { group: rightAlignGroup } )
],
align: 'bottom',
centerX: 0,
spacing: SPACING,
bottom: xAxis.centerY,
stretch: false
} );

Multilink.multilink(
[
leftNumberProperty,
Expand All @@ -259,10 +236,22 @@ export default class QuantumMeasurementHistogram extends Node {
( leftNumber, rightNumber ) => {
const leftProportion = totalNumberProperty.value ? leftNumber / totalNumberProperty.value : 0;
leftHistogramBar.setRect( 0, 0, options.barWidth, leftProportion * maxBarHeight );
numberBars.bottom = xAxis.centerY;
leftHistogramBar.bottom = xAxis.centerY;
const rightProportion = totalNumberProperty.value ? rightNumber / totalNumberProperty.value : 0;
rightHistogramBar.setRect( 0, 0, options.barWidth, rightProportion * maxBarHeight );
numberBars.bottom = xAxis.centerY;
rightHistogramBar.bottom = xAxis.centerY;

// Update the position of the labels for each of the bars.
leftNumberDisplay.centerX = LEFT_HISTOGRAM_BAR_CENTER_X;
rightNumberDisplay.centerX = RIGHT_HISTOGRAM_BAR_CENTER_X;
if ( options.floatingLabels ) {
leftNumberDisplay.bottom = leftHistogramBar.top - FLOATING_LABEL_MARGIN;
rightNumberDisplay.bottom = rightHistogramBar.top - FLOATING_LABEL_MARGIN;
}
else {
leftNumberDisplay.bottom = yAxis.top;
rightNumberDisplay.bottom = yAxis.top;
}
}
);

Expand Down Expand Up @@ -290,16 +279,18 @@ export default class QuantumMeasurementHistogram extends Node {
tickMarkRelatedChildren.push( topTickMarkLabel );
}

// TODO: Why do alignboxes treat us so poorly? https://github.com/phetsims/quantum-measurement/issues/22
options.children = [
new Node( {
children: [
numberBars,
leftHistogramBar,
rightHistogramBar,
yAxis,
...tickMarkRelatedChildren,
xAxis,
xAxisLabels,
numberDisplays
xAxisLeftLabel,
xAxisRightLabel,
leftNumberDisplay,
rightNumberDisplay
]
} )
];
Expand All @@ -308,8 +299,6 @@ export default class QuantumMeasurementHistogram extends Node {

this.xAxis = xAxis;
this.yAxis = yAxis;
this.leftHistogramBar = leftHistogramBar;
this.rightHistogramBar = rightHistogramBar;
this.maxBarHeight = maxBarHeight;
}
}
Expand Down
2 changes: 1 addition & 1 deletion js/photons/view/PhotonsExperimentSceneView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ export default class PhotonsExperimentSceneView extends Node {
const countHistogram = new QuantumMeasurementHistogram(
verticalValueProperty,
horizontalValueProperty,
new BooleanProperty( true ),
[
new RichText(
'V',
Expand All @@ -149,6 +148,7 @@ export default class PhotonsExperimentSceneView extends Node {
{
displayMode: model.laser.emissionMode === 'singlePhoton' ? 'fraction' : 'rate',
orientation: 'horizontal',
floatingLabels: true,
matchLabelColors: true,
leftFillColorProperty: QuantumMeasurementColors.verticalPolarizationColorProperty,
rightFillColorProperty: QuantumMeasurementColors.horizontalPolarizationColorProperty,
Expand Down
3 changes: 1 addition & 2 deletions js/spin/view/HistogramWithExpectedValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ export default class HistogramWithExpectedValue extends QuantumMeasurementHistog
rightNumberProperty: TReadOnlyProperty<number>,
leftProbabilityProperty: TReadOnlyProperty<number>,
expectedValueVisibleProperty: TReadOnlyProperty<boolean>,
displayValuesProperty: TReadOnlyProperty<boolean>,
providedXAxisLabels: [ RichText, RichText ],
providedOptions: QuantumMeasurementHistogramOptions ) {

super( leftNumberProperty, rightNumberProperty, displayValuesProperty, providedXAxisLabels, providedOptions );
super( leftNumberProperty, rightNumberProperty, providedXAxisLabels, providedOptions );

const expectedValueOptions = combineOptions<PathOptions>( {
visibleProperty: expectedValueVisibleProperty
Expand Down
2 changes: 0 additions & 2 deletions js/spin/view/SpinMeasurementArea.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
* @author Agustín Vallejo
*/

import BooleanProperty from '../../../../axon/js/BooleanProperty.js';
import DerivedProperty from '../../../../axon/js/DerivedProperty.js';
import DerivedStringProperty from '../../../../axon/js/DerivedStringProperty.js';
import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js';
Expand Down Expand Up @@ -160,7 +159,6 @@ export default class SpinMeasurementArea extends VBox {
sternGerlach.downCounterProperty,
sternGerlach.upProbabilityProperty,
model.expectedPercentageVisibleProperty,
new BooleanProperty( true ),
[
new RichText( spinUpLabelStringProperty, { font: new PhetFont( { size: 17, weight: 'bold' } ) } ),
new RichText( spinDownLabelStringProperty, { font: new PhetFont( { size: 17, weight: 'bold' } ) } )
Expand Down

0 comments on commit 568a8f2

Please sign in to comment.