Skip to content

Commit

Permalink
RectangularButton: Preferred size and content scaling improvements fo…
Browse files Browse the repository at this point in the history
…r content, see phetsims/scenery#1513
  • Loading branch information
jonathanolson committed Jun 21, 2024
1 parent 7c2499b commit f241fa1
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 23 deletions.
18 changes: 12 additions & 6 deletions js/buttons/ButtonNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export default class ButtonNode extends Sizable( Voicing( Node ) ) {
private readonly _pressListener: PressListener;
private readonly disposeButtonNode: () => void;
protected readonly content: Node | null;
public readonly contentContainer: Node | null = null; // (sun-only)
protected readonly layoutSizeProperty: TinyProperty<Dimension2> = new TinyProperty<Dimension2>( new Dimension2( 0, 0 ) );

// The maximum lineWidth our buttonBackground can have. We'll lay things out so that if we adjust our lineWidth below
Expand Down Expand Up @@ -205,14 +206,19 @@ export default class ButtonNode extends Sizable( Voicing( Node ) ) {
let updateAlignBounds: UnknownMultilink | null = null;

if ( options.content ) {
const content = options.content;

// For performance, in case content is a complicated icon or shape.
// See https://github.com/phetsims/sun/issues/654#issuecomment-718944669
content.pickable = false;
// Container here that can get scaled/positioned/pickable-modified, without affecting the provided content.
this.contentContainer = new Node( {
children: [
options.content
],

// For performance, in case content is a complicated icon or shape.
// See https://github.com/phetsims/sun/issues/654#issuecomment-718944669
pickable: false
} );

// Align content in the button rectangle. Must be disposed since it adds listener to content bounds.
alignBox = new AlignBox( content, {
alignBox = new AlignBox( this.contentContainer, {
xAlign: options.xAlign,
yAlign: options.yAlign,

Expand Down
47 changes: 30 additions & 17 deletions js/buttons/RectangularButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,19 +147,6 @@ export default class RectangularButton extends ButtonNode {

super( buttonModel, buttonBackground, interactionStateProperty, options );

// TODO: get this to work dynamically? Or do we always want things scaled down?
if ( options.size && options.content ) {
const previousContent = options.content;
const minScale = Math.min(
( options.size.width - options.xMargin * 2 ) / previousContent.width,
( options.size.height - options.yMargin * 2 ) / previousContent.height );

options.content = new Node( {
children: [ previousContent ],
scale: minScale
} );
}

this.buttonNodeConstraint = new RectangularButtonNodeConstraint( this, this.layoutSizeProperty, {
content: options.content ?? null,
size: options.size,
Expand Down Expand Up @@ -498,14 +485,19 @@ class RectangularButtonNodeConstraint extends LayoutConstraint {
const contentWidthSizable = !!content && isWidthSizable( content );
const contentHeightSizable = !!content && isHeightSizable( content );

let contentMinimumWidthWithMargins = Math.max( this.minWidth, content ? ( contentWidthSizable ? content.minimumWidth ?? 0 : content.width ) + this.xMargin * 2 : 0 );
let contentMinimumHeightWithMargins = Math.max( this.minHeight, content ? ( contentHeightSizable ? content.minimumHeight ?? 0 : content.height ) + this.yMargin * 2 : 0 );
let contentMinimumWidthWithMargins = content ? ( contentWidthSizable ? content.minimumWidth ?? 0 : content.width ) + this.xMargin * 2 : 0;
let contentMinimumHeightWithMargins = content ? ( contentHeightSizable ? content.minimumHeight ?? 0 : content.height ) + this.yMargin * 2 : 0;

// If a initial (minimum) size is specified, use this as an override (and we will scale the content down to fit)
if ( this.size ) {
contentMinimumWidthWithMargins = Math.max( contentMinimumWidthWithMargins, this.size.width );
contentMinimumHeightWithMargins = Math.max( contentMinimumHeightWithMargins, this.size.height );
contentMinimumWidthWithMargins = this.size.width;
contentMinimumHeightWithMargins = this.size.height;
}

// Apply minWidth/minHeight
contentMinimumWidthWithMargins = Math.max( this.minWidth, contentMinimumWidthWithMargins );
contentMinimumHeightWithMargins = Math.max( this.minHeight, contentMinimumHeightWithMargins );

// Only allow an initial update if we are not sizable in that dimension
let minimumWidth =
( this.isFirstLayout || widthSizable )
Expand Down Expand Up @@ -550,6 +542,27 @@ class RectangularButtonNodeConstraint extends LayoutConstraint {
.shiftedXY( this.mouseAreaXShift, this.mouseAreaYShift );
}

const preferredContentWidth = this.lastLocalWidth - this.xMargin * 2;
const preferredContentHeight = this.lastLocalHeight - this.yMargin * 2;

assert && assert( preferredContentWidth > 0 );
assert && assert( preferredContentHeight > 0 );

if ( this.content ) {
if ( contentWidthSizable ) {
content.preferredWidth = Math.max( preferredContentWidth, content.minimumWidth ?? 0 );
}
if ( contentHeightSizable ) {
content.preferredHeight = Math.max( preferredContentHeight, content.minimumHeight ?? 0 );
}

const contentContainer = this.buttonNode.contentContainer!;
assert && assert( contentContainer );

contentContainer.maxWidth = preferredContentWidth;
contentContainer.maxHeight = preferredContentHeight;
}

this.isFirstLayout = false;

this.layoutSizeProperty.value = new Dimension2( this.lastLocalWidth, this.lastLocalHeight );
Expand Down

0 comments on commit f241fa1

Please sign in to comment.