Skip to content

Commit

Permalink
Create checkboxes as needed, see #153
Browse files Browse the repository at this point in the history
  • Loading branch information
samreid committed Apr 26, 2023
1 parent 1c86200 commit 3012ebe
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 100 deletions.
155 changes: 82 additions & 73 deletions js/common/view/BottomRepresentationCheckboxGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,21 @@
* @author Sam Reid (PhET Interactive Simulations)
*/

import optionize from '../../../../phet-core/js/optionize.js';
import Property from '../../../../axon/js/Property.js';
import Tandem from '../../../../tandem/js/Tandem.js';
import ArrowNode from '../../../../scenery-phet/js/ArrowNode.js';
import centerAndVariability from '../../centerAndVariability.js';
import VerticalCheckboxGroup, { VerticalCheckboxGroupItem, VerticalCheckboxGroupOptions } from '../../../../sun/js/VerticalCheckboxGroup.js';
import VerticalCheckboxGroup, { VerticalCheckboxGroupItem } from '../../../../sun/js/VerticalCheckboxGroup.js';
import { AlignGroup, GridBox, Node, TColor, Text } from '../../../../scenery/js/imports.js';
import CAVModel from '../model/CAVModel.js';
import CAVConstants from '../CAVConstants.js';
import CenterAndVariabilityStrings from '../../CenterAndVariabilityStrings.js';
import CAVColors from '../CAVColors.js';
import NumberLineNode from './NumberLineNode.js';
import PickRequired from '../../../../phet-core/js/types/PickRequired.js';
import PredictionThumbNode from './PredictionThumbNode.js';
import LinkableProperty from '../../../../axon/js/LinkableProperty.js';
import VariabilityModel from '../../variability/model/VariabilityModel.js';

type SelfOptions = {

// TODO: Let each class create exactly what they want without these options
includeMedian: boolean;
includeMean: boolean;
includePredictMean: boolean;
includePredictMedian: boolean;
includeVariability: boolean;
};
export type BottomRepresentationCheckboxGroupOptions = SelfOptions & VerticalCheckboxGroupOptions &
PickRequired<VerticalCheckboxGroupOptions, 'tandem'>;

// constants
const TEXT_OPTIONS = {
font: CAVConstants.BUTTON_FONT,
Expand All @@ -44,73 +30,96 @@ const TEXT_OPTIONS = {

export default class BottomRepresentationCheckboxGroup extends VerticalCheckboxGroup {

public constructor( model: CAVModel, providedOptions?: BottomRepresentationCheckboxGroupOptions ) {

const options = optionize<BottomRepresentationCheckboxGroupOptions, SelfOptions, VerticalCheckboxGroupOptions>()( {
}, providedOptions );

const items: VerticalCheckboxGroupItem[] = [];
const iconGroup = new AlignGroup();

const newGridBox = ( text: Node, icon: Node ) => {
return new GridBox( {
stretch: true,
spacing: 5,
grow: 1,
rows: [ [

// TODO: this will be odd to a11y because both buttons have the same text. Do we have alt text for the icons? Or maybe we need alt text for the entire checkbox?
new Node( { children: [ text ], layoutOptions: { xAlign: 'left' } } ),
iconGroup.createBox( icon, { layoutOptions: { xAlign: 'right' }, xAlign: 'center' } )
] ]
} );
};

const createPredictionItem = ( property: Property<boolean>, stringProperty: LinkableProperty<string>, color: TColor, spacing: number,
tandemName: string ) => {
return {
createNode: ( tandem: Tandem ) => newGridBox( new Text( stringProperty, TEXT_OPTIONS ), new PredictionThumbNode( { color: color, maxHeight: 20, pickable: false } ) ),
property: property,
tandemName: tandemName
};
};

options.includePredictMedian && items.push( createPredictionItem( model.isShowingMedianPredictionProperty,
CenterAndVariabilityStrings.predictMedianStringProperty, CAVColors.medianColorProperty, 8, 'predictMedianCheckbox'
) );
options.includePredictMean && items.push( createPredictionItem( model.isShowingMeanPredictionProperty,
CenterAndVariabilityStrings.predictMeanStringProperty, CAVColors.meanColorProperty, 20.3, 'predictMeanCheckbox'
) );
private static newGridBox( text: Node, icon: Node, iconGroup: AlignGroup ): GridBox {
return new GridBox( {
stretch: true,
spacing: 5,
grow: 1,
rows: [ [

// TODO: this will be odd to a11y because both buttons have the same text. Do we have alt text for the icons? Or maybe we need alt text for the entire checkbox?
new Node( { children: [ text ], layoutOptions: { xAlign: 'left' } } ),
iconGroup.createBox( icon, { layoutOptions: { xAlign: 'right' }, xAlign: 'center' } )
] ]
} );
}

options.includeVariability && items.push( {
createNode: ( tandem: Tandem ) => newGridBox( new Text( CenterAndVariabilityStrings.variabilityStringProperty, TEXT_OPTIONS ),
NumberLineNode.createMeanIndicatorNode( true, true ) ),
property: ( model as VariabilityModel ).isShowingPlayAreaVariabilityProperty,
public static getVariabilityCheckbox( alignGroup: AlignGroup, model: VariabilityModel ): VerticalCheckboxGroupItem {
return {
createNode: ( tandem: Tandem ) => {
return BottomRepresentationCheckboxGroup.newGridBox(
new Text( CenterAndVariabilityStrings.variabilityStringProperty, TEXT_OPTIONS ),
NumberLineNode.createMeanIndicatorNode( true, true ),
alignGroup
);
},
property: model.isShowingPlayAreaVariabilityProperty,
tandemName: 'variabilityCheckbox'
} );
};
}

options.includeMedian && items.push( {
createNode: ( tandem: Tandem ) => newGridBox( new Text( CenterAndVariabilityStrings.medianStringProperty, TEXT_OPTIONS ),
new ArrowNode( 0, 0, 0, 27, {
fill: CAVColors.medianColorProperty,
stroke: CAVColors.arrowStrokeProperty,
lineWidth: CAVConstants.ARROW_LINE_WIDTH,
headHeight: 12,
headWidth: 18,
maxHeight: 20
} ) ),
public static getMedianCheckbox( alignGroup: AlignGroup, model: CAVModel ): VerticalCheckboxGroupItem {
return {
createNode: ( tandem: Tandem ) => {
return BottomRepresentationCheckboxGroup.newGridBox(
new Text( CenterAndVariabilityStrings.medianStringProperty, TEXT_OPTIONS ),
new ArrowNode( 0, 0, 0, 27, {
fill: CAVColors.medianColorProperty,
stroke: CAVColors.arrowStrokeProperty,
lineWidth: CAVConstants.ARROW_LINE_WIDTH,
headHeight: 12,
headWidth: 18,
maxHeight: 20
} ), alignGroup );
},
property: model.isShowingPlayAreaMedianProperty,
tandemName: 'medianCheckbox'
} );
};
}

options.includeMean && items.push( {
createNode: ( tandem: Tandem ) => newGridBox( new Text( CenterAndVariabilityStrings.meanStringProperty, TEXT_OPTIONS ),
NumberLineNode.createMeanIndicatorNode( true, true ) ),
public static getMeanCheckbox( alignGroup: AlignGroup, model: CAVModel ): VerticalCheckboxGroupItem {
return {
createNode: ( tandem: Tandem ) => BottomRepresentationCheckboxGroup.newGridBox( new Text( CenterAndVariabilityStrings.meanStringProperty, TEXT_OPTIONS ),
NumberLineNode.createMeanIndicatorNode( true, true ), alignGroup ),
property: model.isShowingPlayAreaMeanProperty,
tandemName: 'meanCheckbox'
} );
};
}

private static createPredictionItem( property: Property<boolean>, stringProperty: LinkableProperty<string>, color: TColor, spacing: number,
tandemName: string, alignGroup: AlignGroup ): VerticalCheckboxGroupItem {
return {
createNode: ( tandem: Tandem ) => {
return BottomRepresentationCheckboxGroup.newGridBox(
new Text( stringProperty, TEXT_OPTIONS ),
new PredictionThumbNode( { color: color, maxHeight: 20, pickable: false } ),
alignGroup );
},
property: property,
tandemName: tandemName
};
}

public static getPredictMedianCheckbox( alignGroup: AlignGroup, model: CAVModel ): VerticalCheckboxGroupItem {
return BottomRepresentationCheckboxGroup.createPredictionItem(
model.isShowingMedianPredictionProperty,
CenterAndVariabilityStrings.predictMedianStringProperty,
CAVColors.medianColorProperty,
8,
'predictMedianCheckbox',
alignGroup
);
}

super( items, options );
public static getPredictMeanCheckbox( alignGroup: AlignGroup, model: CAVModel ): VerticalCheckboxGroupItem {
return BottomRepresentationCheckboxGroup.createPredictionItem(
model.isShowingMeanPredictionProperty,
CenterAndVariabilityStrings.predictMeanStringProperty,
CAVColors.meanColorProperty,
20.3,
'predictMeanCheckbox',
alignGroup
);
}
}

Expand Down
25 changes: 16 additions & 9 deletions js/mean-and-median/view/MeanAndMedianScreenView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ import centerAndVariability from '../../centerAndVariability.js';
import MeanAndMedianModel from '../model/MeanAndMedianModel.js';
import CAVColors from '../../common/CAVColors.js';
import CenterAndVariabilityStrings from '../../CenterAndVariabilityStrings.js';
import { AlignBox, ManualConstraint, Node } from '../../../../scenery/js/imports.js';
import { AlignBox, AlignGroup, ManualConstraint, Node } from '../../../../scenery/js/imports.js';
import StrictOmit from '../../../../phet-core/js/types/StrictOmit.js';
import CAVScreenView, { CAVScreenViewOptions } from '../../common/view/CAVScreenView.js';
import Bounds2 from '../../../../dot/js/Bounds2.js';
import Tandem from '../../../../tandem/js/Tandem.js';
import MeanAndMedianAccordionBox from './MeanAndMedianAccordionBox.js';
import BottomRepresentationCheckboxGroup from '../../common/view/BottomRepresentationCheckboxGroup.js';
import VerticalCheckboxGroup from '../../../../sun/js/VerticalCheckboxGroup.js';

type MeanAndMedianScreenViewOptions = StrictOmit<CAVScreenViewOptions, 'questionBarOptions'>;

Expand Down Expand Up @@ -46,12 +47,13 @@ export default class MeanAndMedianScreenView extends CAVScreenView {
contentsWrapper.x = playAreaNumberLineNodeWrapper.x;
} );

const bottomCheckboxGroup = new BottomRepresentationCheckboxGroup( model, {
includeMean: true,
includePredictMean: true,
includePredictMedian: true,
includeMedian: true,
includeVariability: false,
const iconGroup = new AlignGroup();
const bottomCheckboxGroup = new VerticalCheckboxGroup( [
BottomRepresentationCheckboxGroup.getPredictMedianCheckbox( iconGroup, model ),
BottomRepresentationCheckboxGroup.getPredictMeanCheckbox( iconGroup, model ),
BottomRepresentationCheckboxGroup.getMedianCheckbox( iconGroup, model ),
BottomRepresentationCheckboxGroup.getMeanCheckbox( iconGroup, model )
], {
tandem: options.tandem.createTandem( 'bottomCheckboxGroup' )
} );

Expand All @@ -60,8 +62,13 @@ export default class MeanAndMedianScreenView extends CAVScreenView {
const BOTTOM_CHECKBOX_PANEL_MARGIN = 12.5;
const BOTTOM_CHECKBOX_PANEL_Y_MARGIN = this.layoutBounds.maxY - this.modelViewTransform.modelToViewY( 0 ) + BOTTOM_CHECKBOX_PANEL_MARGIN;

const checkboxAlignBox = new AlignBox( bottomCheckboxGroup, { alignBounds: this.layoutBounds, xAlign: 'right', yAlign: 'bottom', xMargin: BOTTOM_CHECKBOX_PANEL_MARGIN, yMargin: BOTTOM_CHECKBOX_PANEL_Y_MARGIN } );
this.addChild( checkboxAlignBox );
this.addChild( new AlignBox( bottomCheckboxGroup, {
alignBounds: this.layoutBounds,
xAlign: 'right',
yAlign: 'bottom',
xMargin: BOTTOM_CHECKBOX_PANEL_MARGIN,
yMargin: BOTTOM_CHECKBOX_PANEL_Y_MARGIN
} ) );
}
}

Expand Down
23 changes: 14 additions & 9 deletions js/median/view/MedianScreenView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import Bounds2 from '../../../../dot/js/Bounds2.js';
import Tandem from '../../../../tandem/js/Tandem.js';
import MedianAccordionBox from './MedianAccordionBox.js';
import BottomRepresentationCheckboxGroup from '../../common/view/BottomRepresentationCheckboxGroup.js';
import { AlignBox } from '../../../../scenery/js/imports.js';
import { AlignBox, AlignGroup } from '../../../../scenery/js/imports.js';
import VerticalCheckboxGroup from '../../../../sun/js/VerticalCheckboxGroup.js';

type SelfOptions = EmptySelfOptions;
type MedianScreenViewOptions =
Expand All @@ -43,21 +44,25 @@ export default class MedianScreenView extends CAVScreenView {
( tandem: Tandem, top: number, layoutBounds: Bounds2 ) =>
new MedianAccordionBox( model, layoutBounds, tandem, top ), options );

const bottomCheckboxGroup = new BottomRepresentationCheckboxGroup( model, {
includeMean: false,
includePredictMean: false,
includePredictMedian: true,
includeMedian: true,
includeVariability: false,
const iconGroup = new AlignGroup();
const bottomCheckboxGroup = new VerticalCheckboxGroup( [
BottomRepresentationCheckboxGroup.getPredictMedianCheckbox( iconGroup, model ),
BottomRepresentationCheckboxGroup.getMedianCheckbox( iconGroup, model )
], {
tandem: options.tandem.createTandem( 'bottomCheckboxGroup' )
} );

// In order to use the AlignBox we need to know the distance from the top of the screen, to the top of the grass.
const BOTTOM_CHECKBOX_PANEL_MARGIN = 12.5;
const BOTTOM_CHECKBOX_PANEL_Y_MARGIN = this.layoutBounds.maxY - this.modelViewTransform.modelToViewY( 0 ) + BOTTOM_CHECKBOX_PANEL_MARGIN;

const checkboxAlignBox = new AlignBox( bottomCheckboxGroup, { alignBounds: this.layoutBounds, xAlign: 'right', yAlign: 'bottom', xMargin: BOTTOM_CHECKBOX_PANEL_MARGIN, yMargin: BOTTOM_CHECKBOX_PANEL_Y_MARGIN } );
this.addChild( checkboxAlignBox );
this.addChild( new AlignBox( bottomCheckboxGroup, {
alignBounds: this.layoutBounds,
xAlign: 'right',
yAlign: 'bottom',
xMargin: BOTTOM_CHECKBOX_PANEL_MARGIN,
yMargin: BOTTOM_CHECKBOX_PANEL_Y_MARGIN
} ) );
}
}

Expand Down
23 changes: 14 additions & 9 deletions js/variability/view/VariabilityScreenView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import centerAndVariability from '../../centerAndVariability.js';
import VariabilityModel from '../model/VariabilityModel.js';
import CAVColors from '../../common/CAVColors.js';
import CenterAndVariabilityStrings from '../../CenterAndVariabilityStrings.js';
import { AlignBox, ManualConstraint, Node } from '../../../../scenery/js/imports.js';
import { AlignBox, AlignGroup, ManualConstraint, Node } from '../../../../scenery/js/imports.js';
import DistributionRadioButtonGroup from './DistributionRadioButtonGroup.js';
import VariabilityMeasureRadioButtonGroup from './VariabilityMeasureRadioButtonGroup.js';
import InfoDialog from './InfoDialog.js';
Expand All @@ -23,6 +23,7 @@ import Bounds2 from '../../../../dot/js/Bounds2.js';
import Tandem from '../../../../tandem/js/Tandem.js';
import VariabilityAccordionBox from './VariabilityAccordionBox.js';
import BottomRepresentationCheckboxGroup from '../../common/view/BottomRepresentationCheckboxGroup.js';
import VerticalCheckboxGroup from '../../../../sun/js/VerticalCheckboxGroup.js';

type SelfOptions = EmptySelfOptions;
type VariabilityScreenViewOptions = SelfOptions & StrictOmit<CAVScreenViewOptions, 'questionBarOptions'>;
Expand Down Expand Up @@ -90,12 +91,12 @@ export default class VariabilityScreenView extends CAVScreenView {
}
} );

const bottomCheckboxGroup = new BottomRepresentationCheckboxGroup( model, {
includeVariability: true,
includePredictMean: false,
includePredictMedian: false,
includeMean: true,
includeMedian: true,
const iconGroup = new AlignGroup();
const bottomCheckboxGroup = new VerticalCheckboxGroup( [
BottomRepresentationCheckboxGroup.getVariabilityCheckbox( iconGroup, model ),
BottomRepresentationCheckboxGroup.getMedianCheckbox( iconGroup, model ),
BottomRepresentationCheckboxGroup.getMeanCheckbox( iconGroup, model )
], {
tandem: options.tandem.createTandem( 'bottomCheckboxGroup' )
} );

Expand All @@ -104,8 +105,12 @@ export default class VariabilityScreenView extends CAVScreenView {
const BOTTOM_CHECKBOX_PANEL_MARGIN = 12.5;
const BOTTOM_CHECKBOX_PANEL_Y_MARGIN = this.layoutBounds.maxY - this.modelViewTransform.modelToViewY( 0 ) + BOTTOM_CHECKBOX_PANEL_MARGIN;

const checkboxAlignBox = new AlignBox( bottomCheckboxGroup, { alignBounds: this.layoutBounds, xAlign: 'right', yAlign: 'bottom', xMargin: BOTTOM_CHECKBOX_PANEL_MARGIN, yMargin: BOTTOM_CHECKBOX_PANEL_Y_MARGIN } );
this.addChild( checkboxAlignBox );
this.addChild( new AlignBox( bottomCheckboxGroup, {
alignBounds: this.layoutBounds,
xAlign: 'right', yAlign: 'bottom',
xMargin: BOTTOM_CHECKBOX_PANEL_MARGIN,
yMargin: BOTTOM_CHECKBOX_PANEL_Y_MARGIN
} ) );
}
}

Expand Down

0 comments on commit 3012ebe

Please sign in to comment.