Skip to content

Commit

Permalink
Split text input padding into 2 separate properties (#7338)
Browse files Browse the repository at this point in the history
Don't show in changelog
  • Loading branch information
AlexandreSi authored Jan 23, 2025
1 parent 56ab2fd commit c4e230d
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 44 deletions.
73 changes: 52 additions & 21 deletions Extensions/TextInput/JsExtension.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,11 @@ module.exports = {
} else if (propertyName === 'maxLength') {
objectContent.maxLength = newValue;
return true;
} else if (propertyName === 'padding') {
objectContent.padding = newValue;
} else if (propertyName === 'paddingX') {
objectContent.paddingX = Math.max(0, parseFloat(newValue));
return true;
} else if (propertyName === 'paddingY') {
objectContent.paddingY = Math.max(0, parseFloat(newValue));
return true;
} else if (propertyName === 'textAlign') {
objectContent.textAlign = newValue;
Expand Down Expand Up @@ -210,11 +213,27 @@ module.exports = {
.setGroup(_('Border appearance'));

objectProperties
.getOrCreate('padding')
.setValue((objectContent.padding || 0).toString())
.getOrCreate('paddingX')
.setValue(
(objectContent.paddingX !== undefined
? objectContent.paddingX
: 2
).toString()
)
.setType('number')
.setLabel(_('Padding'))
.setGroup(_('Font'));
.setLabel(_('Padding (horizontal)'))
.setGroup(_('Field appearance'));
objectProperties
.getOrCreate('paddingY')
.setValue(
(objectContent.paddingY !== undefined
? objectContent.paddingY
: 1
).toString()
)
.setType('number')
.setLabel(_('Padding (vertical)'))
.setGroup(_('Field appearance'));
objectProperties
.getOrCreate('maxLength')
.setValue((objectContent.maxLength || 0).toString())
Expand All @@ -235,7 +254,7 @@ module.exports = {
.addExtraInfo('center')
.addExtraInfo('right')
.setLabel(_('Text alignment'))
.setGroup(_('Font'));
.setGroup(_('Field appearance'));

return objectProperties;
};
Expand All @@ -253,7 +272,8 @@ module.exports = {
borderWidth: 1,
readOnly: false,
disabled: false,
padding: 0,
paddingX: 2,
paddingY: 1,
textAlign: 'left',
maxLength: 0,
};
Expand Down Expand Up @@ -683,7 +703,6 @@ module.exports = {

const DEFAULT_WIDTH = 300;
const DEFAULT_HEIGHT = 30;
const TEXT_MASK_PADDING = 2;

class RenderedTextInputObjectInstance extends RenderedInstance {
constructor(
Expand Down Expand Up @@ -797,39 +816,51 @@ module.exports = {
);

const borderWidth = object.content.borderWidth || 0;
const paddingX =
object.content.paddingX !== undefined
? Math.min(
parseFloat(object.content.paddingX),
width / 2 - borderWidth
)
: 2;
const paddingY =
object.content.paddingY !== undefined
? Math.min(
parseFloat(object.content.paddingY),
height / 2 - borderWidth
)
: 1;

// Draw the mask for the text.
const textOffset = borderWidth + TEXT_MASK_PADDING;
const textOffsetX = borderWidth + paddingX;
// textOffsetY does not include the paddingY because browsers display the text, even if it is supposed to be cut off by vertical padding.
const textOffsetY = borderWidth;
this._pixiTextMask.clear();
this._pixiTextMask.beginFill(0xdddddd, 1);
this._pixiTextMask.drawRect(
textOffset,
textOffset,
width - 2 * textOffset,
height - 2 * textOffset
textOffsetX,
textOffsetY,
width - 2 * textOffsetX,
height - 2 * textOffsetY
);
this._pixiTextMask.endFill();

const isTextArea = object.content.inputType === 'text area';
const textAlign = object.content.textAlign
? object.content.textAlign
: 'left';
const padding = object.content.padding
? parseFloat(object.content.padding)
: 0;

if (textAlign === 'left')
this._pixiText.position.x = textOffset + padding;
if (textAlign === 'left') this._pixiText.position.x = textOffsetX;
else if (textAlign === 'right')
this._pixiText.position.x =
0 + width - this._pixiText.width - textOffset - padding;
0 + width - this._pixiText.width - textOffsetX;
else if (textAlign === 'center') {
this._pixiText.align = 'center';
this._pixiText.position.x = 0 + width / 2 - this._pixiText.width / 2;
}

this._pixiText.position.y = isTextArea
? textOffset
? textOffsetY + paddingY
: height / 2 - this._pixiText.height / 2;

// Draw the background and border.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ describe('gdjs.TextInputRuntimeObject (using a PixiJS RuntimeGame with DOM eleme
borderWidth: 2,
disabled: false,
readOnly: false,
padding: 0,
paddingX: 2,
paddingY: 1,
textAlign: 'left',
maxLength: 20,
},
Expand Down
16 changes: 11 additions & 5 deletions Extensions/TextInput/textinputruntimeobject-pixi-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,23 @@ namespace gdjs {
this._form.style.borderRadius = '0px';
this._form.style.backgroundColor = 'transparent';
this._form.style.position = 'absolute';
this._form.style.outline = 'none';
this._form.style.resize = 'none';
this._form.style.pointerEvents = 'auto'; // Element can be clicked/touched.
this._form.style.display = 'none'; // Hide while object is being set up.
this._form.style.boxSizing = 'border-box';
this._form.style.textAlign = this._object.getTextAlign();

this._input.autocomplete = 'off';
this._input.style.backgroundColor = 'white';
this._input.style.outline = 'none'; // Remove any style added by the browser to highlight the focused field in a form (:focus & :focus-visible modifiers).
this._input.style.resize = 'none'; // Prevent user from resizing the input when it's a text area.
this._input.style.border = '1px solid black';
this._input.style.boxSizing = 'border-box';
this._input.style.width = '100%';
this._input.style.height = '100%';
this._input.maxLength = this._object.getMaxLength();
this._input.style.padding = this._object.getPadding() + 'px';
this._input.style.padding = `${this._object
.getPaddingY()
.toFixed(2)}px ${this._object.getPaddingX().toFixed(2)}px`;

this._form.appendChild(this._input);

Expand Down Expand Up @@ -240,7 +242,9 @@ namespace gdjs {
'rotate3d(0,0,1,' + (this._object.getAngle() % 360) + 'deg)';
this._form.style.textAlign = this._object.getTextAlign();

this._input.style.padding = this._object.getPadding() + 'px';
this._input.style.padding = `${this._object
.getPaddingY()
.toFixed(2)}px ${this._object.getPaddingX().toFixed(2)}px`;

// Automatically adjust the font size to follow the game scale.
this._input.style.fontSize =
Expand Down Expand Up @@ -345,7 +349,9 @@ namespace gdjs {
updatePadding() {
if (!this._input) return;

this._input.style.padding = this._object.getPadding() + 'px';
this._input.style.padding = `${this._object
.getPaddingY()
.toFixed(2)}px ${this._object.getPaddingX().toFixed(2)}px`;
}

updateTextAlign() {
Expand Down
72 changes: 55 additions & 17 deletions Extensions/TextInput/textinputruntimeobject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,17 @@ namespace gdjs {
textColor: string;
fillColor: string;
fillOpacity: float;
padding?: float;
textAlign?: SupportedTextAlign;
maxLength?: integer;
borderColor: string;
borderOpacity: float;
borderWidth: float;
disabled: boolean;
readOnly: boolean;
// ---- Values can be undefined because of support for these feature was added in v5.5.222.
paddingX?: float;
paddingY?: float;
textAlign?: SupportedTextAlign;
maxLength?: integer;
// ----
};
}

Expand Down Expand Up @@ -84,6 +87,10 @@ namespace gdjs {
const DEFAULT_WIDTH = 300;
const DEFAULT_HEIGHT = 30;

const clampPadding = (value: float, dimension: float, borderWidth: float) => {
return Math.max(0, Math.min(dimension / 2 - borderWidth, value));
};

/**
* Shows a text input on the screen the player can type text into.
*/
Expand All @@ -101,7 +108,8 @@ namespace gdjs {
private _textColor: [float, float, float];
private _fillColor: [float, float, float];
private _fillOpacity: float;
private _padding: integer;
private _paddingX: integer;
private _paddingY: integer;
private _textAlign: SupportedTextAlign;
private _maxLength: integer;
private _borderColor: [float, float, float];
Expand Down Expand Up @@ -133,9 +141,16 @@ namespace gdjs {
this._borderWidth = objectData.content.borderWidth;
this._disabled = objectData.content.disabled;
this._readOnly = objectData.content.readOnly;
this._textAlign = parseTextAlign(objectData.content.textAlign); //textAlign is defaulted to 'left' by the parser if undefined.
this._maxLength = objectData.content.maxLength || 0; //maxlength and padding require a default value as they can be undefined in older projects.
this._padding = objectData.content.padding || 0;
this._textAlign = parseTextAlign(objectData.content.textAlign);
this._maxLength = objectData.content.maxLength || 0;
this._paddingX =
objectData.content.paddingX !== undefined
? objectData.content.paddingX
: 2;
this._paddingY =
objectData.content.paddingY !== undefined
? objectData.content.paddingY
: 1;
this._isSubmitted = false;
this._renderer = new gdjs.TextInputRuntimeObjectRenderer(
this,
Expand Down Expand Up @@ -213,7 +228,7 @@ namespace gdjs {
this.setReadOnly(newObjectData.content.readOnly);
}
if (
newObjectData.content.maxLength &&
newObjectData.content.maxLength !== undefined &&
oldObjectData.content.maxLength !== newObjectData.content.maxLength
) {
this.setMaxLength(newObjectData.content.maxLength);
Expand All @@ -225,10 +240,16 @@ namespace gdjs {
this._textAlign = newObjectData.content.textAlign;
}
if (
newObjectData.content.padding &&
oldObjectData.content.padding !== newObjectData.content.padding
newObjectData.content.paddingX !== undefined &&
oldObjectData.content.paddingX !== newObjectData.content.paddingX
) {
this.setPadding(newObjectData.content.padding);
this.setPaddingX(newObjectData.content.paddingX);
}
if (
newObjectData.content.paddingY !== undefined &&
oldObjectData.content.paddingY !== newObjectData.content.paddingY
) {
this.setPaddingY(newObjectData.content.paddingY);
}

return true;
Expand Down Expand Up @@ -296,6 +317,7 @@ namespace gdjs {
if (initialInstanceData.customSize) {
this.setWidth(initialInstanceData.width);
this.setHeight(initialInstanceData.height);
this._renderer.updatePadding();
}
if (initialInstanceData.opacity !== undefined) {
this.setOpacity(initialInstanceData.opacity);
Expand Down Expand Up @@ -331,10 +353,12 @@ namespace gdjs {

setWidth(width: float): void {
this._width = width;
this._renderer.updatePadding();
}

setHeight(height: float): void {
this._height = height;
this._renderer.updatePadding();
}

/**
Expand Down Expand Up @@ -560,17 +584,31 @@ namespace gdjs {
this._maxLength = value;
this._renderer.updateMaxLength();
}
getPadding(): integer {
return this._padding;

getPaddingX(): integer {
return clampPadding(this._paddingX, this._width, this._borderWidth);
}
setPaddingX(value: integer) {
if (this._paddingX === value) return;
if (value < 0) {
this._paddingX = 0;
return;
}

this._paddingX = value;
this._renderer.updatePadding();
}
getPaddingY(): integer {
return clampPadding(this._paddingY, this._height, this._borderWidth);
}
setPadding(value: integer) {
if (this._padding === value) return;
setPaddingY(value: integer) {
if (this._paddingY === value) return;
if (value < 0) {
this._padding = 0;
this._paddingY = 0;
return;
}

this._padding = value;
this._paddingY = value;
this._renderer.updatePadding();
}

Expand Down

0 comments on commit c4e230d

Please sign in to comment.